lydown 0.6.1 → 0.6.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 768154bba0df3c6550e92d7bab1846d78e767652
4
- data.tar.gz: a964448d153898925ee16869131f9888a1298ca2
3
+ metadata.gz: 8b8c837a068f50dd59adac76af318ea85b9e27c0
4
+ data.tar.gz: a2c3297624f4682fda2c3484334955488a7911ec
5
5
  SHA512:
6
- metadata.gz: fdc5ae5af05d007763399b2e33b4d7c7ab98050f2abbfd2ffc2f84a49fa8ed6e907762aed1ea577c58bbe98a5ff3d44ab21e11a9382fcd02a830719740fda29d
7
- data.tar.gz: 286f620033bd8c01c53bd1dffacb6d715264d4a135674389d892b5602e8c4d23fc3f55f540514a75a1e46b499316cea09766aa9764252e2e9b02b64332e76ab3
6
+ metadata.gz: 105a386ac25d493b6621877cc983508c41a7e00ee6fa6c5a2d3dc61ceef5358ffce2d0a54ae3f06d71076c884a347b341ee9614b0d67315e2995756b4dfce4af
7
+ data.tar.gz: 441484711848e46815d6cbbba3478dfc54b37d4bcfab1bb1e5171bed91100f6393da6845f1daca92b005c9baf303c88f66c52a0ea9ee461fe3157486b7969368
data/README.md CHANGED
@@ -94,6 +94,10 @@ Notes can be repeated using the <code>@</code> placeholder:
94
94
 
95
95
  (The repeating note placeholder is useful when entering repeated notes with accidentals).
96
96
 
97
+ Chords are written using angled brackets, like in lilypond:
98
+
99
+ (2<fd>4<ge>) => <f d>2( <g e>4)
100
+
97
101
  ### Rests
98
102
 
99
103
  Normal rests are written [like in lilypond](http://www.lilypond.org/doc/v2.18/Documentation/notation/writing-rests#rests):
@@ -284,6 +288,10 @@ Multiple arguments can be given, separated by colons. Arguments need to be quote
284
288
 
285
289
  \!override:AccidentalSuggestion:"#'avoid-slur = #'outside"
286
290
 
291
+ Some lilypond command arguments are expected to be quoted. Quotes can be escaped by prefixing them with a backslash:
292
+
293
+ \footnote:"#'(-1 . 1)":"\"slurred?\""
294
+
287
295
  ### Inline lyrics
288
296
 
289
297
  Lyrics for vocal parts can be entered on separate lines prefixed by a > symbol:
@@ -108,6 +108,28 @@ class String
108
108
  def camelize
109
109
  split('_').collect(&:capitalize).join
110
110
  end
111
+
112
+ # String unescaping code from here: http://stackoverflow.com/a/20131717
113
+
114
+ UNESCAPES = {
115
+ 'a' => "\x07", 'b' => "\x08", 't' => "\x09",
116
+ 'n' => "\x0a", 'v' => "\x0b", 'f' => "\x0c",
117
+ 'r' => "\x0d", 'e' => "\x1b", "\\\\" => "\x5c",
118
+ "\"" => "\x22", "'" => "\x27"
119
+ }
120
+
121
+ def unescape
122
+ # Escape all the things
123
+ gsub(/\\(?:([#{UNESCAPES.keys.join}])|u([\da-fA-F]{4}))|\\0?x([\da-fA-F]{2})/) {
124
+ if $1
125
+ if $1 == '\\' then '\\' else UNESCAPES[$1] end
126
+ elsif $2 # escape \u0000 unicode
127
+ ["#$2".hex].pack('U*')
128
+ elsif $3 # escape \0xff or \xff
129
+ [$3].pack('H2')
130
+ end
131
+ }
132
+ end
111
133
  end
112
134
 
113
135
  class Fixnum
@@ -45,7 +45,7 @@ grammar Lydown
45
45
  end
46
46
  rule event
47
47
  (inline_command / inline_lyrics / voice_selector / barline / duration /
48
- note / standalone_figures / rest / silence / phrasing / tie) white_space*
48
+ chord / note / standalone_figures / rest / silence / phrasing / tie) white_space*
49
49
  end
50
50
  rule barline
51
51
  ('?|' / ':|][|:' / '[|:' / ':|]' / [\|\.\:]+) <Barline>
@@ -88,6 +88,9 @@ grammar Lydown
88
88
  rule note
89
89
  note_head octave* accidental_flag? figures? expression* <Note>
90
90
  end
91
+ rule chord
92
+ '<' note white_space* (note white_space*)* '>' expression* <Chord>
93
+ end
91
94
  rule expression
92
95
  (expression_shorthand / expression_longhand / string) <Note::Expression>
93
96
  end
@@ -114,6 +114,16 @@ module Lydown::Parsing
114
114
  end
115
115
  end
116
116
  end
117
+
118
+ module Chord
119
+ include Root
120
+
121
+ def to_stream(stream)
122
+ chord = {type: :chord, notes: []}
123
+ _to_stream(self, chord[:notes])
124
+ stream << chord
125
+ end
126
+ end
117
127
 
118
128
  module FiguresComponent
119
129
  def to_stream(note)
@@ -271,7 +281,7 @@ module Lydown::Parsing
271
281
  module Argument
272
282
  def to_stream(cmd)
273
283
  if text_value =~ /^"(.+)"$/
274
- value = $1
284
+ value = $1.unescape
275
285
  else
276
286
  value = text_value
277
287
  end
@@ -1,231 +1,7 @@
1
1
  require 'lydown/rendering/figures'
2
+ require 'lydown/rendering/notes'
2
3
 
3
4
  module Lydown::Rendering
4
- module Accidentals
5
- KEY_CYCLE = %w{c- g- d- a- e- b- f c g d a e b f+ c+ g+ d+ a+ e+ b+}
6
- C_IDX = KEY_CYCLE.index('c'); A_IDX = KEY_CYCLE.index('a')
7
- SHARPS_IDX = KEY_CYCLE.index('f+'); FLATS_IDX = KEY_CYCLE.index('b-')
8
- KEY_ACCIDENTALS = {}
9
-
10
- def self.accidentals_for_key_signature(signature)
11
- KEY_ACCIDENTALS[signature] ||= calc_accidentals_for_key_signature(signature)
12
- end
13
-
14
- def self.calc_accidentals_for_key_signature(signature)
15
- unless signature =~ /^([a-g][\+\-]*) (major|minor)$/
16
- raise "Invalid key signature #{signature.inspect}"
17
- end
18
-
19
- key = $1; mode = $2
20
-
21
- # calculate offset from c major / a minor
22
- base_idx = (mode == 'major') ? C_IDX : A_IDX
23
- offset = KEY_CYCLE.index(key) - base_idx
24
-
25
- if offset >= 0
26
- calc_accidentals_map(KEY_CYCLE[SHARPS_IDX, offset])
27
- else
28
- calc_accidentals_map(KEY_CYCLE[FLATS_IDX + offset + 1, -offset])
29
- end
30
- end
31
-
32
- def self.calc_accidentals_map(accidentals)
33
- accidentals.inject({}) { |h, a| h[a[0]] = (a[1] == '+') ? 1 : -1; h}
34
- end
35
-
36
- def self.lilypond_note_name(note, key_signature = 'c major')
37
- value = 0
38
- # accidental value from note
39
- note = note.gsub(/[\-\+]/) { |c| value += (c == '+') ? 1 : -1; '' }
40
- # add key signature value
41
- value += accidentals_for_key_signature(key_signature)[note] || 0
42
-
43
- note + (value >= 0 ? 'is' * value : 'es' * -value)
44
- end
45
-
46
- # Takes into account the accidentals mode
47
- def self.translate_note_name(work, note)
48
- if work[:accidentals] == 'manual'
49
- key = 'c major'
50
- else
51
- key = work[:key]
52
- end
53
- lilypond_note_name(note, key)
54
- end
55
- end
56
-
57
- module Notes
58
- include Lydown::Rendering::Figures
59
-
60
- def add_note(event)
61
- return add_macro_note(event) if @work['process/duration_macro']
62
-
63
- if @event[:head] == '@'
64
- # replace repeating note head
65
- @event[:head] = @work['process/last_note_head']
66
- else
67
- @work['process/last_note_head'] = event[:head]
68
- end
69
-
70
- value = @work['process/duration_values'].first
71
- @work['process/duration_values'].rotate!
72
-
73
- add_figures(event[:figures], value) if event[:figures]
74
-
75
- # push value into running values accumulator. This is used to synthesize
76
- # the bass figures durations.
77
- unless event[:figures]
78
- @work['process/running_values'] ||= []
79
- if event[:rest_value]
80
- @work['process/running_values'] << event[:rest_value]
81
- else
82
- @work['process/running_values'] << value
83
- end
84
- end
85
-
86
- # only add the value if different than the last used
87
- if value == @work['process/last_value']
88
- value = ''
89
- else
90
- @work['process/last_value'] = value
91
- end
92
-
93
- @work.emit(event[:stream] || :music, lilypond_note(event, value: value))
94
- end
95
-
96
- FICTA_CODE = <<EOF
97
- \\once \\override AccidentalSuggestion #'avoid-slur = #'outside
98
- \\once \\set suggestAccidentals = ##t
99
- EOF
100
-
101
- def lilypond_note(event, options = {})
102
- head = Accidentals.translate_note_name(@work, event[:head])
103
- if options[:head_only]
104
- head
105
- else
106
- if event[:accidental_flag] == '^'
107
- accidental_flag = ''
108
- prefix = FICTA_CODE
109
- else
110
- accidental_flag = event[:accidental_flag]
111
- prefix = ''
112
- end
113
-
114
- [
115
- prefix,
116
- head,
117
- event[:octave],
118
- accidental_flag,
119
- options[:value],
120
- lilypond_phrasing(event),
121
- event[:expressions] ? event[:expressions].join : '',
122
- ' '
123
- ].join
124
- end
125
- end
126
-
127
- def lilypond_phrasing(event)
128
- phrasing = ''
129
- if @work['process/open_beam']
130
- phrasing << '['
131
- @work['process/open_beam'] = nil
132
- end
133
- if @work['process/open_slur']
134
- phrasing << '('
135
- @work['process/open_slur'] = nil
136
- end
137
- phrasing << ']' if event[:beam_close]
138
- phrasing << ')' if event[:slur_close]
139
- phrasing
140
- end
141
-
142
- def lydown_phrasing_open(event)
143
- phrasing = ''
144
- if @work['process/open_beam']
145
- phrasing << '['
146
- @work['process/open_beam'] = nil
147
- end
148
- if @work['process/open_slur']
149
- phrasing << '('
150
- @work['process/open_slur'] = nil
151
- end
152
- phrasing
153
- end
154
-
155
- def lydown_phrasing_close(event)
156
- phrasing = ''
157
- phrasing << ']' if event[:beam_close]
158
- phrasing << ')' if event[:slur_close]
159
- phrasing
160
- end
161
-
162
- def add_macro_note(event)
163
- @work['process/macro_group'] ||= @work['process/duration_macro'].clone
164
- underscore_count = 0
165
-
166
- lydown_note = "%s%s%s%s%s%s%s" % [
167
- lydown_phrasing_open(event),
168
- event[:head], event[:octave], event[:accidental_flag],
169
- lydown_phrasing_close(event),
170
- event[:figures] ? "<#{event[:figures].join}>" : '',
171
- event[:expressions] ? event[:expressions].join : ''
172
- ]
173
-
174
- # replace place holder and repeaters in macro group with actual note
175
- @work['process/macro_group'].gsub!(/[_∞]/) do |match|
176
- case match
177
- when '_'
178
- underscore_count += 1
179
- underscore_count == 1 ? lydown_note : match
180
- when '∞'
181
- underscore_count < 2 ? event[:head] : match
182
- end
183
- end
184
-
185
- # if group is complete, compile it just like regular code
186
- unless @work['process/macro_group'].include?('_')
187
- # stash macro, in order to compile macro group
188
- macro = @work['process/duration_macro']
189
- @work['process/duration_macro'] = nil
190
-
191
- code = LydownParser.parse(@work['process/macro_group'])
192
- @work.process(code, no_reset: true)
193
-
194
- # restore macro
195
- @work['process/duration_macro'] = macro
196
- @work['process/macro_group'] = nil
197
- end
198
- end
199
-
200
- LILYPOND_EXPRESSIONS = {
201
- '_' => '--',
202
- '.' => '-.',
203
- '`' => '-!'
204
- }
205
-
206
- def translate_expressions
207
- return unless @event[:expressions]
208
-
209
- @event[:expressions] = @event[:expressions].map do |expr|
210
- if expr =~ /^(?:\\(_?))?"(.+)"$/
211
- placement = ($1 == '_') ? '_' : '^'
212
- "#{placement}\\markup { #{translate_string_expression($2)} }"
213
- elsif expr =~ /^\\/
214
- expr
215
- elsif LILYPOND_EXPRESSIONS[expr]
216
- LILYPOND_EXPRESSIONS[expr]
217
- else
218
- raise LydownError, "Invalid expression #{expr.inspect}"
219
- end
220
- end
221
- end
222
-
223
- def translate_string_expression(expr)
224
- expr.gsub(/__([^_]+)__/) {|m| "\\bold { #{$1} }" }.
225
- gsub(/_([^_]+)_/) {|m| "\\italic { #{$1} }" }
226
- end
227
- end
228
-
229
5
  LILYPOND_DURATIONS = {
230
6
  '6' => '16',
231
7
  '3' => '32'
@@ -294,6 +70,27 @@ EOF
294
70
  add_note(@event)
295
71
  end
296
72
  end
73
+
74
+ class Chord < Base
75
+ include Notes
76
+
77
+ def translate
78
+ look_ahead_idx = @idx + 1
79
+ while event = @stream[look_ahead_idx]
80
+ case event[:type]
81
+ when :beam_close
82
+ @event[:beam_close] = true
83
+ when :slur_close
84
+ @event[:slur_close] = true
85
+ else
86
+ break
87
+ end
88
+ look_ahead_idx += 1
89
+ end
90
+
91
+ add_chord(@event)
92
+ end
93
+ end
297
94
 
298
95
  class StandAloneFigures < Base
299
96
  include Notes
@@ -359,6 +156,7 @@ EOF
359
156
 
360
157
  if @event[:multiplier]
361
158
  value = full_bar_value(@work[:time])
159
+ @work['process/duration_macro'] = nil unless @work['process/macro_group']
362
160
  if value
363
161
  @event[:rest_value] = "#{value}*#{@event[:multiplier]}"
364
162
  @event[:head] = "#{@event[:head]}#{@event[:rest_value]}"
@@ -0,0 +1,273 @@
1
+ require 'lydown/rendering/figures'
2
+
3
+ module Lydown::Rendering
4
+ module Accidentals
5
+ KEY_CYCLE = %w{c- g- d- a- e- b- f c g d a e b f+ c+ g+ d+ a+ e+ b+}
6
+ C_IDX = KEY_CYCLE.index('c'); A_IDX = KEY_CYCLE.index('a')
7
+ SHARPS_IDX = KEY_CYCLE.index('f+'); FLATS_IDX = KEY_CYCLE.index('b-')
8
+ KEY_ACCIDENTALS = {}
9
+
10
+ def self.accidentals_for_key_signature(signature)
11
+ KEY_ACCIDENTALS[signature] ||= calc_accidentals_for_key_signature(signature)
12
+ end
13
+
14
+ def self.calc_accidentals_for_key_signature(signature)
15
+ unless signature =~ /^([a-g][\+\-]*) (major|minor)$/
16
+ raise "Invalid key signature #{signature.inspect}"
17
+ end
18
+
19
+ key = $1; mode = $2
20
+
21
+ # calculate offset from c major / a minor
22
+ base_idx = (mode == 'major') ? C_IDX : A_IDX
23
+ offset = KEY_CYCLE.index(key) - base_idx
24
+
25
+ if offset >= 0
26
+ calc_accidentals_map(KEY_CYCLE[SHARPS_IDX, offset])
27
+ else
28
+ calc_accidentals_map(KEY_CYCLE[FLATS_IDX + offset + 1, -offset])
29
+ end
30
+ end
31
+
32
+ def self.calc_accidentals_map(accidentals)
33
+ accidentals.inject({}) { |h, a| h[a[0]] = (a[1] == '+') ? 1 : -1; h}
34
+ end
35
+
36
+ def self.lilypond_note_name(note, key_signature = 'c major')
37
+ value = 0
38
+ # accidental value from note
39
+ note = note.gsub(/[\-\+]/) { |c| value += (c == '+') ? 1 : -1; '' }
40
+ # add key signature value
41
+ value += accidentals_for_key_signature(key_signature)[note] || 0
42
+
43
+ note + (value >= 0 ? 'is' * value : 'es' * -value)
44
+ end
45
+
46
+ # Takes into account the accidentals mode
47
+ def self.translate_note_name(work, note)
48
+ if work[:accidentals] == 'manual'
49
+ key = 'c major'
50
+ else
51
+ key = work[:key]
52
+ end
53
+ lilypond_note_name(note, key)
54
+ end
55
+ end
56
+
57
+ module Notes
58
+ include Lydown::Rendering::Figures
59
+
60
+ def add_note(event, options = {})
61
+ return add_macro_note(event) if @work['process/duration_macro']
62
+
63
+ if @event[:head] == '@'
64
+ # replace repeating note head
65
+ @event[:head] = @work['process/last_note_head']
66
+ else
67
+ @work['process/last_note_head'] = event[:head]
68
+ end
69
+
70
+ value = @work['process/duration_values'].first
71
+ @work['process/duration_values'].rotate!
72
+
73
+ add_figures(event[:figures], value) if event[:figures]
74
+
75
+ # push value into running values accumulator. This is used to synthesize
76
+ # the bass figures durations.
77
+ unless event[:figures]
78
+ @work['process/running_values'] ||= []
79
+ if event[:rest_value]
80
+ @work['process/running_values'] << event[:rest_value]
81
+ else
82
+ @work['process/running_values'] << value
83
+ end
84
+ end
85
+
86
+ # only add the value if different than the last used
87
+ if options[:no_value] || (value == @work['process/last_value'])
88
+ value = ''
89
+ else
90
+ @work['process/last_value'] = value
91
+ end
92
+
93
+ code = lilypond_note(event, options.merge(value: value))
94
+ @work.emit(event[:stream] || :music, code)
95
+ end
96
+
97
+ def add_chord(event, options = {})
98
+ value = @work['process/duration_values'].first
99
+ @work['process/duration_values'].rotate!
100
+
101
+ add_figures(event[:figures], value) if event[:figures]
102
+
103
+ # push value into running values accumulator. This is used to synthesize
104
+ # the bass figures durations.
105
+ unless event[:figures]
106
+ @work['process/running_values'] ||= []
107
+ if event[:rest_value]
108
+ @work['process/running_values'] << event[:rest_value]
109
+ else
110
+ @work['process/running_values'] << value
111
+ end
112
+ end
113
+
114
+ # only add the value if different than the last used
115
+ if value == @work['process/last_value']
116
+ value = ''
117
+ else
118
+ @work['process/last_value'] = value
119
+ end
120
+
121
+ notes = event[:notes].map do |note|
122
+ lilypond_note(note)
123
+ end
124
+
125
+ options = options.merge(value: value)
126
+ @work.emit(event[:stream] || :music, lilypond_chord(event, notes, options))
127
+ end
128
+
129
+ FICTA_CODE = <<EOF
130
+ \\once \\override AccidentalSuggestion #'avoid-slur = #'outside
131
+ \\once \\set suggestAccidentals = ##t
132
+ EOF
133
+
134
+ def lilypond_note(event, options = {})
135
+ head = Accidentals.translate_note_name(@work, event[:head])
136
+ if options[:head_only]
137
+ head
138
+ else
139
+ if event[:accidental_flag] == '^'
140
+ accidental_flag = ''
141
+ prefix = FICTA_CODE
142
+ else
143
+ accidental_flag = event[:accidental_flag]
144
+ prefix = ''
145
+ end
146
+
147
+ [
148
+ prefix,
149
+ head,
150
+ event[:octave],
151
+ accidental_flag,
152
+ options[:value],
153
+ lilypond_phrasing(event),
154
+ event[:expressions] ? event[:expressions].join : '',
155
+ options[:no_whitespace] ? '' : ' '
156
+ ].join
157
+ end
158
+ end
159
+
160
+ def lilypond_chord(event, notes, options = {})
161
+ [
162
+ '<',
163
+ notes.join(' ').strip, # strip trailing whitespace
164
+ '>',
165
+ options[:value],
166
+ lilypond_phrasing(event),
167
+ event[:expressions] ? event[:expressions].join : '',
168
+ ].join
169
+ end
170
+
171
+ def lilypond_phrasing(event)
172
+ phrasing = ''
173
+ if @work['process/open_beam']
174
+ phrasing << '['
175
+ @work['process/open_beam'] = nil
176
+ end
177
+ if @work['process/open_slur']
178
+ phrasing << '('
179
+ @work['process/open_slur'] = nil
180
+ end
181
+ phrasing << ']' if event[:beam_close]
182
+ phrasing << ')' if event[:slur_close]
183
+ phrasing
184
+ end
185
+
186
+ def lydown_phrasing_open(event)
187
+ phrasing = ''
188
+ if @work['process/open_beam']
189
+ phrasing << '['
190
+ @work['process/open_beam'] = nil
191
+ end
192
+ if @work['process/open_slur']
193
+ phrasing << '('
194
+ @work['process/open_slur'] = nil
195
+ end
196
+ phrasing
197
+ end
198
+
199
+ def lydown_phrasing_close(event)
200
+ phrasing = ''
201
+ phrasing << ']' if event[:beam_close]
202
+ phrasing << ')' if event[:slur_close]
203
+ phrasing
204
+ end
205
+
206
+ def add_macro_note(event)
207
+ @work['process/macro_group'] ||= @work['process/duration_macro'].clone
208
+ underscore_count = 0
209
+
210
+ lydown_note = "%s%s%s%s%s%s%s" % [
211
+ lydown_phrasing_open(event),
212
+ event[:head], event[:octave], event[:accidental_flag],
213
+ lydown_phrasing_close(event),
214
+ event[:figures] ? "<#{event[:figures].join}>" : '',
215
+ event[:expressions] ? event[:expressions].join : ''
216
+ ]
217
+
218
+ # replace place holder and repeaters in macro group with actual note
219
+ @work['process/macro_group'].gsub!(/[_∞]/) do |match|
220
+ case match
221
+ when '_'
222
+ underscore_count += 1
223
+ underscore_count == 1 ? lydown_note : match
224
+ when '∞'
225
+ underscore_count < 2 ? event[:head] : match
226
+ end
227
+ end
228
+
229
+ # if group is complete, compile it just like regular code
230
+ unless @work['process/macro_group'].include?('_')
231
+ # stash macro, in order to compile macro group
232
+ macro = @work['process/duration_macro']
233
+ @work['process/duration_macro'] = nil
234
+
235
+ code = LydownParser.parse(@work['process/macro_group'])
236
+ @work.process(code, no_reset: true)
237
+
238
+ # restore macro
239
+ @work['process/duration_macro'] = macro
240
+ @work['process/macro_group'] = nil
241
+ end
242
+ end
243
+
244
+ LILYPOND_EXPRESSIONS = {
245
+ '_' => '--',
246
+ '.' => '-.',
247
+ '`' => '-!'
248
+ }
249
+
250
+ def translate_expressions
251
+ return unless @event[:expressions]
252
+
253
+ @event[:expressions] = @event[:expressions].map do |expr|
254
+ if expr =~ /^(?:\\(_?))?"(.+)"$/
255
+ placement = ($1 == '_') ? '_' : '^'
256
+ "#{placement}\\markup { #{translate_string_expression($2)} }"
257
+ elsif expr =~ /^\\/
258
+ expr
259
+ elsif LILYPOND_EXPRESSIONS[expr]
260
+ LILYPOND_EXPRESSIONS[expr]
261
+ else
262
+ raise LydownError, "Invalid expression #{expr.inspect}"
263
+ end
264
+ end
265
+ end
266
+
267
+ def translate_string_expression(expr)
268
+ expr.unescape.
269
+ gsub(/__([^_]+)__/) {|m| "\\bold { #{$1} }" }.
270
+ gsub(/_([^_]+)_/) {|m| "\\italic { #{$1} }" }
271
+ end
272
+ end
273
+ end
@@ -3,6 +3,7 @@ require 'lydown/work'
3
3
  require 'lydown/rendering/base'
4
4
  require 'lydown/rendering/comments'
5
5
  require 'lydown/rendering/lyrics'
6
+ require 'lydown/rendering/notes'
6
7
  require 'lydown/rendering/music'
7
8
  require 'lydown/rendering/settings'
8
9
  require 'lydown/rendering/staff'
@@ -1,3 +1,3 @@
1
1
  module Lydown
2
- VERSION = "0.6.1"
2
+ VERSION = "0.6.2"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lydown
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.1
4
+ version: 0.6.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sharon Rosner
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-06-13 00:00:00.000000000 Z
11
+ date: 2015-06-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: treetop
@@ -50,6 +50,7 @@ files:
50
50
  - lib/lydown/rendering/lyrics.rb
51
51
  - lib/lydown/rendering/movement.rb
52
52
  - lib/lydown/rendering/music.rb
53
+ - lib/lydown/rendering/notes.rb
53
54
  - lib/lydown/rendering/settings.rb
54
55
  - lib/lydown/rendering/staff.rb
55
56
  - lib/lydown/rendering/voices.rb