Permalink
Browse files

[#22] I should be able to add repeats and alternatives.

  • Loading branch information...
1 parent c670e7e commit 68d765ea4a82155c3d8c49e1c492bdb973e389e8 @gsmendoza committed Mar 27, 2012
@@ -0,0 +1,117 @@
+\version "2.12.3"
+\include "english.ly"
+
+\paper {
+ indent = #0
+}
+
+\header {
+ title = ""
+ composer = ""
+ arranger = ""
+ instrument = ""
+}
+
+%-----------------------------------------------------------------------
+% Chord Sets
+%-----------------------------------------------------------------------
+% Bars
+
+vOneBarTabOneLineOneRepeatOneBarOne = { c4 d e f }
+cBarTabOneLineOneRepeatOneBarOne = { }
+sBarTabOneLineOneRepeatOneBarOne = { r1 }
+
+vOneBarTabOneLineOneAlternativeOneBarOne = { d2 e }
+cBarTabOneLineOneAlternativeOneBarOne = { }
+sBarTabOneLineOneAlternativeOneBarOne = { r1 }
+
+vOneBarTabOneLineOneAlternativeOneBarTwo = { f2 g }
+cBarTabOneLineOneAlternativeOneBarTwo = { }
+sBarTabOneLineOneAlternativeOneBarTwo = { r1 }
+%-----------------------------------------------------------------------
+% Lines
+
+vOneLineTabOneLineOne = { \repeat volta 4 { \vOneBarTabOneLineOneRepeatOneBarOne } \alternative { { \vOneBarTabOneLineOneAlternativeOneBarOne } { \vOneBarTabOneLineOneAlternativeOneBarTwo } } \break }
+cLineTabOneLineOne = { \repeat volta 4 { \cBarTabOneLineOneRepeatOneBarOne } \alternative { { \cBarTabOneLineOneAlternativeOneBarOne } { \cBarTabOneLineOneAlternativeOneBarTwo } } }
+sLineTabOneLineOne = { \repeat volta 4 { \sBarTabOneLineOneRepeatOneBarOne } \alternative { { \sBarTabOneLineOneAlternativeOneBarOne } { \sBarTabOneLineOneAlternativeOneBarTwo } } }
+%-----------------------------------------------------------------------
+% Stanzas
+%-----------------------------------------------------------------------
+% Scores
+%-----------------------------------------------------------------------
+% Voices
+
+vOne = {
+ \vOneLineTabOneLineOne
+}
+%-----------------------------------------------------------------------
+% Stanza Headings
+
+stanzaHeadings = { \sLineTabOneLineOne }
+
+%-----------------------------------------------------------------------
+% Chord Headings
+
+chordHeadings = { \cLineTabOneLineOne }
+
+%-----------------------------------------------------------------------
+
+\score {
+ \new StaffGroup <<
+ \new Staff <<
+ \clef "treble_8"
+
+ \new Voice \with { \remove Rest_engraver } {
+ \stanzaHeadings
+ }
+
+ \new Voice {
+ \voiceOne
+ \vOne
+ }
+ >>
+
+ \new TabStaff <<
+ \new TabVoice {
+ \slurUp
+ \vOne
+ }
+ \new TabVoice {
+ \chordHeadings
+ }
+ >>
+ >>
+
+ \layout {
+ \context { \Staff
+ \override TimeSignature #'style = #'numbered
+ \override StringNumber #'transparent = ##t
+ }
+ \context { \TabStaff
+ \override TimeSignature #'style = #'numbered
+ }
+ \context { \Voice
+ \remove Slur_engraver
+ }
+ \context { \TabVoice
+ \remove Dots_engraver
+ \remove Stem_engraver
+ \remove Rest_engraver
+ }
+ }
+}
+
+% showLastLength = R1*4
+\score {
+ \new Staff \with {midiInstrument = #"acoustic guitar (nylon)"} <<
+ \clef "treble_8"
+
+ \new Voice {
+ \unfoldRepeats {
+ \vOne
+ }
+ }
+ >>
+
+ \midi {}
+}
@@ -0,0 +1,19 @@
+Gitara.define do
+ line do
+ repeat 4 do
+ bar do
+ notes "c4 d e f"
+ end
+ end
+
+ alternative do
+ bar do
+ notes "d2 e"
+ end
+
+ bar do
+ notes "f2 g"
+ end
+ end
+ end
+end
View
@@ -13,6 +13,7 @@
require "gitara/node/base/chorded_version"
require "gitara/node/base/stanza_version"
require "gitara/node/base/voiced_version"
+require "gitara/node/alternative"
require "gitara/node/bar"
require "gitara/node/bar/chorded_version"
require "gitara/node/bar/stanza_version"
@@ -21,6 +22,7 @@
require "gitara/node/chord_set/chorded_version"
require "gitara/node/line"
require "gitara/node/note_set"
+require "gitara/node/repeat"
require "gitara/node/score"
require "gitara/node/stanza"
require "gitara/node/tab"
View
@@ -30,6 +30,10 @@ def add_names(options = {}, &block)
end
end
+ def alternative(&block)
+ add Node::Alternative.new, &block
+ end
+
def bar(*names, &block)
add_names :names => names, :node_class => Node::Bar, &block
end
@@ -50,6 +54,10 @@ def partial(duration)
node.specified_duration = duration
end
+ def repeat(value, &block)
+ add Node::Repeat.new(:value => value), &block
+ end
+
def score(*names, &block)
add_names :names => names, :node_class => Node::Score, &block
end
@@ -0,0 +1,14 @@
+module Gitara
+ module Node
+ class Alternative < Base
+ def call_value(node_version)
+ alternatives = node_version.definition_children.map do |child|
+ "{ #{child.call_value} }"
+ end
+
+ "\\alternative { #{alternatives.join(' ')} }"
+ end
+ end
+ end
+end
+
View
@@ -16,6 +16,10 @@ def ancestor(klass)
ancestors.detect{|ancestor| ancestor.is_a?(klass)}
end
+ def call_value(node_version)
+ node_version.call_name
+ end
+
def definition_children
if leaf?
definition ? definition.children : []
@@ -84,7 +88,7 @@ def stanza_version
end
def value
- attributes[:value] ? attributes[:value].gsub('/', "\\") : nil
+ attributes[:value].respond_to?(:gsub) ? attributes[:value].gsub('/', "\\") : attributes[:value]
end
def voiced_as(arg)
@@ -8,6 +8,10 @@ def call_name
"\\#{definition_name}"
end
+ def call_value
+ node.call_value(self)
+ end
+
def definition_children
node.definition_children.map{|child| self.class.new(:node => child)}
end
@@ -21,7 +25,7 @@ def prefix
end
def value
- definition_children.map(&:call_name).join(' ')
+ definition_children.map(&:call_value).join(' ')
end
end
end
View
@@ -0,0 +1,10 @@
+module Gitara
+ module Node
+ class Repeat < Base
+ def call_value(node_version)
+ "\\repeat volta #{value} { #{ node_version.value } }"
+ end
+ end
+ end
+end
+
View
@@ -2,6 +2,9 @@
factory :note_set, :class => Node::NoteSet do
end
+ factory :alternative, :class => Node::Alternative do
+ end
+
factory :app, :class => App do
end
@@ -28,6 +31,9 @@
children [FactoryGirl.build(:bar)]
end
+ factory :repeat, :class => Node::Repeat do
+ end
+
factory :stanza, :class => Node::Stanza do
children [FactoryGirl.build(:line)]
end
@@ -25,5 +25,11 @@
app_test.run
app_test.actual.should == app_test.expected
end
+
+ it "can convert a tab with repeats to lilypond" do
+ app_test = AppTester.new(:name => 'tab-with-repeats')
+ app_test.run
+ app_test.actual.should == app_test.expected
+ end
end
end
@@ -255,5 +255,52 @@
dsl.node.specified_duration.should == 8
end
end
+
+ describe "repeat(value)" do
+ it "should add a repeat with the value" do
+ dsl = FactoryGirl.build(:dsl, :node => FactoryGirl.build(:tab, :children => []))
+
+ dsl.repeat 2
+
+ dsl.node.children.should have(1).repeat
+
+ repeat = dsl.node.children[0]
+ repeat.value.should == 2
+ repeat.children.should be_empty
+ end
+
+ it "should add the children declared in the block to the repeat" do
+ dsl = FactoryGirl.build(:dsl, :node => FactoryGirl.build(:tab, :children => []))
+
+ bar = FactoryGirl.build(:bar)
+
+ dsl.repeat 2 do
+ add bar
+ end
+
+ dsl.node.children.should have(1).repeat
+
+ repeat = dsl.node.children[0]
+ repeat.children.should have(1).child
+ repeat.children[0].should == bar
+ end
+ end
+
+ describe "alternative(value)" do
+ it "should add the children declared in the block to the alternative" do
+ dsl = FactoryGirl.build(:dsl, :node => FactoryGirl.build(:tab, :children => []))
+ bar = FactoryGirl.build(:bar)
+
+ dsl.alternative do
+ add bar
+ end
+
+ dsl.node.children.should have(1).alternative
+
+ alternative = dsl.node.children[0]
+ alternative.children.should have(1).child
+ alternative.children[0].should == bar
+ end
+ end
end
end
@@ -0,0 +1,15 @@
+require 'spec_helper'
+
+describe Node::Alternative do
+ describe "call_value" do
+ it "should be a call to lilypond's alternative command" do
+ alternative = FactoryGirl.build(:alternative, :children => [
+ FactoryGirl.build(:bar, :name => 'First'),
+ FactoryGirl.build(:bar, :name => 'Second')
+ ])
+
+ version = Node::Base::NodeVersion.new(:node => alternative)
+ alternative.call_value(version).should == "\\alternative { { \\nBarFirst } { \\nBarSecond } }"
+ end
+ end
+end
@@ -23,7 +23,7 @@
end
describe "value" do
- it "should be the call names of its definition_children" do
+ it "should be the call values of its definition_children" do
node = FactoryGirl.build(:base, :children => [
FactoryGirl.build(:base, :name => :First),
FactoryGirl.build(:base, :name => :Second)
@@ -47,5 +47,20 @@
children[0].should be_a(Node::Base::NodeVersion)
end
end
+
+ describe "call_value" do
+ it "should be the call name if we want to render the node's definition name in the lilypond output" do
+ node = FactoryGirl.build(:base, :name => 'parent')
+ node_version = Node::Base::NodeVersion.new(:node => node)
+ node_version.call_value.should == '\nBaseParent'
+ end
+
+ it "should be the call value of the node if we don't want to render the node's definition name in the lilypond output" do
+ node = FactoryGirl.build(:base, :name => 'name')
+ node_version = Node::Base::NodeVersion.new(:node => node)
+ node.should_receive(:call_value).with(node_version).and_return("todo { }")
+ node_version.call_value.should == "todo { }"
+ end
+ end
end
@@ -108,6 +108,11 @@
node = FactoryGirl.build(:base, :value => %q|notes "<g'/1>8 <a/3>8 <g'/1>8 <a/3>16 <g'/1>8 <g/3>16 <e'/1>4 <g/3>8"|)
node.value.should == %q|notes "<g'\1>8 <a\3>8 <g'\1>8 <a\3>16 <g'\1>8 <g\3>16 <e'\1>4 <g\3>8"|
end
+
+ it "should work with non-strings" do
+ node = FactoryGirl.build(:base, :value => 1)
+ node.value.should == 1
+ end
end
describe "voiced_as(arg)" do
@@ -264,4 +269,12 @@
bar.ancestor(Node::Stanza).should be_nil
end
end
+
+ describe "call_value(node_version)" do
+ it "should be the call name by default" do
+ node = FactoryGirl.build(:base, :name => 'MyNode')
+ node_version = Node::Base::NodeVersion.new(:node => node)
+ node.call_value(node_version).should == '\nBaseMyNode'
+ end
+ end
end
Oops, something went wrong.

0 comments on commit 68d765e

Please sign in to comment.