lydown 0.6.1 → 0.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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