Skip to content

Commit

Permalink
[#26] Fix: Bar#stanza cannot find the stanza if the stanza's bar is d…
Browse files Browse the repository at this point in the history
…efined outside the stanza.

  Solution: Let Stanza handle #heading_for_first_bar instead of Bar#stanza_heading_for_first_bar.
  • Loading branch information
gsmendoza committed Jan 23, 2013
1 parent ee02759 commit 49ac91b
Show file tree
Hide file tree
Showing 9 changed files with 48 additions and 89 deletions.
2 changes: 1 addition & 1 deletion examples/tab-with-partial.ly
Expand Up @@ -28,7 +28,7 @@ cChordSetD = { r1-"D" }
vOneBarVerseLineOneBarOne = { \partial 8 <g\3>8 }
vTwoBarVerseLineOneBarOne = { \partial 8 r8 }
cBarVerseLineOneBarOne = { \partial 8 \cChordSetGEight }
sBarVerseLineOneBarOne = { \partial 8 r8^"Verse" }
sBarVerseLineOneBarOne = { \partial 8 r8 }

vOneBarVerseLineOneBarTwo = { <a\3>16\glissando <b\3>16 <b\3>4 r16 <a\3>16\glissando <b\3>4. <a\3>16( <g\3>16) }
vTwoBarVerseLineOneBarTwo = { r1 }
Expand Down
2 changes: 1 addition & 1 deletion examples/tab-with-reused-bar-in-stanza.ly
Expand Up @@ -40,7 +40,7 @@ sLineIntroLineOne = { \sBarIntro \sBarIntro \sBarIntro \sBarIntro }
vOneStanzaIntro = { \vOneLineIntroLineOne }
vTwoStanzaIntro = { \vTwoLineIntroLineOne }
cStanzaIntro = { \cLineIntroLineOne }
sStanzaIntro = { r1^"Intro" r r r }
sStanzaIntro = { r1^"Intro" r1 r1 r1 }


%-----------------------------------------------------------------------
Expand Down
2 changes: 1 addition & 1 deletion examples/tab-with-time-signature.ly
Expand Up @@ -19,7 +19,7 @@

vOneBarCChordBarOne = { c4 e4 }
cBarCChordBarOne = { }
sBarCChordBarOne = { r4^"C chord" r4 }
sBarCChordBarOne = { r4 r4 }

vOneBarCChordBarTwo = { g2 }
cBarCChordBarTwo = { }
Expand Down
2 changes: 1 addition & 1 deletion examples/tab.ly
Expand Up @@ -77,7 +77,7 @@ sLineVerseOneLineOne = { \sBarItsNot \sBarWhatYouThought \sBarWhenYouFirst \sBar
vOneStanzaVerseOne = { \vOneLineVerseOneLineOne \vOneLineVerseOneLineTwo }
vTwoStanzaVerseOne = { \vTwoLineVerseOneLineOne \vTwoLineVerseOneLineTwo }
cStanzaVerseOne = { \cLineVerseOneLineOne \cLineVerseOneLineTwo }
sStanzaVerseOne = { r1^"Verse 1" r r r r r r r }
sStanzaVerseOne = { r1^"Verse 1" r1 r1 r1 r1 r1 r1 r1 }


%-----------------------------------------------------------------------
Expand Down
25 changes: 0 additions & 25 deletions lib/gitara/node/bar.rb
Expand Up @@ -5,10 +5,6 @@ class Bar < Base
# @attribute $1
has_value :specified_duration

def first_bar_of_stanza?
stanza && stanza.descendants(Node::Bar)[0] == self
end

def note_sets
definition_children.select{|child| child.is_a?(Node::NoteSet)}
end
Expand All @@ -17,28 +13,7 @@ def specified_duration_as_lilypond
specified_duration ? "\\partial #{specified_duration}" : nil
end

def stanza
self.ancestor(Node::Stanza)
end

def stanza_heading
first_bar_of_stanza? ? stanza_heading_for_first_bar : stanza_heading_for_succeeding_bars
end

def stanza_heading_for_first_bar
if specified_duration
%Q|r#{specified_duration}^"#{ancestor(Node::Stanza).name}"|
else
ts = ancestor(Node::Tab).time_signature
if ts.generates_whole_note_bars?
%Q|#{ts.rest_bar_value}^"#{ancestor(Node::Stanza).name}"|
else
%Q|r#{ts.beat_unit}^"#{ancestor(Node::Stanza).name}" | + ("r#{ts.beat_unit} " * (ts.beats_per_bar - 1)).strip
end
end
end

def stanza_heading_for_succeeding_bars
specified_duration ? "r#{specified_duration}" : ancestor(Node::Tab).time_signature.rest_bar_value
end
end
Expand Down
24 changes: 23 additions & 1 deletion lib/gitara/node/stanza.rb
@@ -1,8 +1,30 @@
module Gitara
module Node
class Stanza < Base
def bars
@bars ||= descendants(Node::Bar)
end

def heading_in_lilypond
descendants(Node::Bar).map(&:stanza_heading).join(' ')
results = (
[self.heading_for_first_bar] +
bars.drop(1).map(&:stanza_heading)
)

results.join(' ')
end

def heading_for_first_bar
if bars[0].specified_duration
%Q|r#{bars[0].specified_duration}^"#{name}"|
else
ts = ancestor(Node::Tab).time_signature
if ts.generates_whole_note_bars?
%Q|#{ts.rest_bar_value}^"#{name}"|
else
%Q|r#{ts.beat_unit}^"#{name}" | + ("r#{ts.beat_unit} " * (ts.beats_per_bar - 1)).strip
end
end
end
end
end
Expand Down
2 changes: 1 addition & 1 deletion spec/lib/gitara/node/bar/stanza_version_spec.rb
Expand Up @@ -8,7 +8,7 @@
tab = FactoryGirl.build(:tab, :children => [stanza], :time => '4/4')

stanza_version_of_bar = FactoryGirl.build(:stanza_version_bar, :node => bar)
stanza_version_of_bar.value.should == 'r1^"Intro"'
stanza_version_of_bar.value.should == 'r1'
end
end
end
Expand Down
60 changes: 2 additions & 58 deletions spec/lib/gitara/node/bar_spec.rb
Expand Up @@ -19,34 +19,16 @@
end

describe "#stanza_heading" do
it "should be a whole rest with the stanza name if the bar is the first node of a stanza" do
bar = FactoryGirl.build(:bar)
stanza = FactoryGirl.build(:stanza, :name => 'Intro', :children => [bar])
tab = FactoryGirl.build(:tab, :children => [stanza], :time => '4/4')

bar.stanza_heading.should == 'r1^"Intro"'
end

it "should be a whole rest with no stanza name if the bar is not the first node of a stanza" do
it "should be a whole rest with no stanza name" do
first_bar = FactoryGirl.build(:bar)
second_bar = FactoryGirl.build(:bar)
stanza = FactoryGirl.build(:stanza, :name => 'Intro', :children => [first_bar, second_bar])
tab = FactoryGirl.build(:tab, :children => [stanza], :time => '4/4')

second_bar.stanza_heading.should == 'r1'
end
end

describe "#with a special_duration" do
it "should be a partial with the stanza name if the bar is the first node of a stanza" do
subject = FactoryGirl.build(:bar, :specified_duration => 8)
stanza = FactoryGirl.build(:stanza, :name => 'Intro', :children => [subject])
tab = FactoryGirl.build(:tab, :children => [stanza], :time => '4/4')

subject.stanza_heading.should == 'r8^"Intro"'
end

it "should be a partial with no stanza name if the subject is not the first node of a stanza" do
it "should be a partial with no stanza name if the bar has a special_duration" do
first_bar = FactoryGirl.build(:bar)
second_bar = FactoryGirl.build(:bar, :specified_duration => 8)
stanza = FactoryGirl.build(:stanza, :name => 'Intro', :children => [first_bar, second_bar])
Expand All @@ -56,26 +38,6 @@
end
end

describe "#first_bar_of_stanza?" do
it "should be true if the bar is the first bar of a stanza" do
bar = FactoryGirl.build(:bar)
stanza = FactoryGirl.build(:stanza, :name => 'Intro', :children => [bar])
bar.should be_first_bar_of_stanza
end

it "should be false if the bar is not the first bar of a stanza" do
bars = [FactoryGirl.build(:bar), FactoryGirl.build(:bar)]
stanza = FactoryGirl.build(:stanza, :name => 'Intro', :children => bars)

bars[1].should_not be_first_bar_of_stanza
end

it "should be false if the bar does not belong to a stanza" do
bar = FactoryGirl.build(:bar)
bar.should_not be_first_bar_of_stanza
end
end

describe "#specified_duration_as_lilypond" do
it "should be \\partial specified_duration if present" do
bar = FactoryGirl.build(:bar, :specified_duration => 8)
Expand All @@ -87,22 +49,4 @@
bar.specified_duration_as_lilypond.should be_nil
end
end

describe "#stanza_heading_for_first_bar" do
it "should be the time signature's rest bar value with the stanza name if the time signature will generate whole note bars" do
bar = FactoryGirl.build(:bar)
stanza = FactoryGirl.build(:stanza, :name => 'Intro', :children => [bar])
tab = FactoryGirl.build(:tab, :children => [stanza], :time => '4/4')

bar.stanza_heading_for_first_bar.should == 'r1^"Intro"'
end

it "should attach the stanza name to the first rest note if the time signature will not generate whole note bars" do
bar = FactoryGirl.build(:bar)
stanza = FactoryGirl.build(:stanza, :name => 'Intro', :children => [bar])
tab = FactoryGirl.build(:tab, :children => [stanza], :time => '3/4')

bar.stanza_heading_for_first_bar.should == 'r4^"Intro" r4 r4'
end
end
end
18 changes: 18 additions & 0 deletions spec/lib/gitara/node/stanza_spec.rb
Expand Up @@ -15,4 +15,22 @@
stanza.heading_in_lilypond.should == 'r1^"Verse 1" r1'
end
end

describe "#heading_for_first_bar" do
it "should be the time signature's rest bar value with the stanza name if the time signature will generate whole note bars" do
bar = FactoryGirl.build(:bar)
stanza = FactoryGirl.build(:stanza, :name => 'Intro', :children => [bar])
tab = FactoryGirl.build(:tab, :children => [stanza], :time => '4/4')

stanza.heading_for_first_bar.should == 'r1^"Intro"'
end

it "should attach the stanza name to the first rest note if the time signature will not generate whole note bars" do
bar = FactoryGirl.build(:bar)
stanza = FactoryGirl.build(:stanza, :name => 'Intro', :children => [bar])
tab = FactoryGirl.build(:tab, :children => [stanza], :time => '3/4')

stanza.heading_for_first_bar.should == 'r4^"Intro" r4 r4'
end
end
end

0 comments on commit 49ac91b

Please sign in to comment.