-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
extract logic of "zipping" music and lyrics to a new class
- Loading branch information
Showing
6 changed files
with
115 additions
and
61 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
module Gly | ||
# knows how to "zip" music and lyric chunks together | ||
class MusicWithLyrics | ||
def initialize(music, lyrics) | ||
@music = music | ||
@lyrics = lyrics | ||
end | ||
|
||
def each_pair | ||
return enum_for(:each_pair) unless block_given? | ||
|
||
lyric_enum = @lyrics.each_syllable.to_enum | ||
|
||
@music.each_with_index do |mus_chunk,i| | ||
begin | ||
next_syl = lyric_enum.peek | ||
yield nil, lyric_enum.next if next_syl == ' ' | ||
rescue StopIteration | ||
next_syl = '' | ||
end until next_syl != ' ' | ||
|
||
if no_lyrics? mus_chunk, next_syl | ||
if i == @music.size - 1 | ||
yield nil, ' ' | ||
end | ||
else | ||
# regular music chunk | ||
begin | ||
lyr = strip_directives lyric_enum.next | ||
rescue StopIteration | ||
lyr = ' ' if i > 0 # don't add space at the very beginning | ||
end | ||
end | ||
|
||
yield mus_chunk, lyr | ||
if no_lyrics?(mus_chunk, next_syl) && | ||
i != (@music.size - 1) && | ||
! @lyrics.empty? | ||
yield nil, ' ' | ||
end | ||
end | ||
end | ||
|
||
private | ||
|
||
def no_lyrics?(music_chunk, syllable) | ||
clef?(music_chunk) || | ||
(nonlyrical_chunk?(music_chunk) && | ||
! nonlyrical_lyrics?(syllable)) | ||
end | ||
|
||
def clef?(chunk) | ||
chunk =~ /\A[cf][1-4]\Z/ | ||
end | ||
|
||
def without_differentiae(chunk) | ||
chunk.gsub /(([,`])|(:[:']?)|(;[1-6]?))/, '' | ||
end | ||
|
||
def without_breaks(chunk) | ||
chunk.gsub /[zZ]/, '' | ||
end | ||
|
||
# is the given music chunk capable of bearing lyrics? | ||
def nonlyrical_chunk?(chunk) | ||
chunk.size > 0 && | ||
without_breaks(without_differentiae(chunk)).empty? | ||
end | ||
|
||
def nonlyrical_lyrics?(syl) | ||
syl =~ /\A\s*!/ || syl =~ /\A\s*\*\Z/ | ||
end | ||
|
||
def strip_directives(syl) | ||
syl.sub(/(\s*)!/, '\1') # exclamation mark at the beginning - place even under nonlyrical music chunk | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
require_relative 'test_helper' | ||
|
||
class TestMusicWithLyrics < GlyTest | ||
include Gly | ||
|
||
def assert_translates(gly, expected) | ||
doc = Parser.new.parse(StringIO.new(gly)) | ||
score = doc.scores[0] | ||
zipped = MusicWithLyrics.new(score.music, score.lyrics) | ||
assert_equal zipped.each_pair.to_a, expected | ||
end | ||
|
||
def two_monosyllabic_words | ||
assert_translates("a a\n\\l i i", [['a', 'i'], [nil, ' '], ['a', 'i']]) | ||
end | ||
|
||
def test_one_word_and_divisio | ||
assert_translates("a a ::\nA -- men", [['a', 'A'], ['a', 'men'], [nil, ' '], ['::', nil]]) | ||
end | ||
|
||
def test_divisio | ||
assert_translates("a , a\n\\l x x", [['a', 'x'], [nil, ' '], [',', nil], [nil, ' '], ['a', 'x']]) | ||
end | ||
|
||
def test_force_under_divisio | ||
assert_translates("a , a\n\\l x !forced x", [['a', 'x'], [nil, ' '], [',', 'forced'], [nil, ' '], ['a', 'x']]) | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters