lydown 0.3.0

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.
@@ -0,0 +1,55 @@
1
+ <%
2
+ title = nil
3
+ if name && (name != '')
4
+ title = Lydown::Rendering.part_title(name)
5
+ end
6
+ id = "#{title && title.gsub(' ', '')}Staff"
7
+
8
+ score_mode = self['render_opts/mode'] == :score
9
+
10
+ clef = Lydown::Rendering::Staff.clef(name)
11
+ beaming_mode = Lydown::Rendering::Staff.beaming_mode(name)
12
+ partial = self[:pickup] ? "\\partial #{self[:pickup]}" : ""
13
+
14
+ end_barline = Lydown::Rendering::Staff.end_barline(self, movement)
15
+
16
+ cadenza = self[:time] == 'unmetered'
17
+ %>
18
+
19
+ <<
20
+
21
+ \new Staff = <%= id %> \with {
22
+ }
23
+
24
+ \context Staff = <%= id %> {
25
+ <% if score_mode %>\set Staff.instrumentName = #"<%= title %>"<% end %>
26
+ \relative c {
27
+ <% if clef %>
28
+ \clef "<%= clef %>"
29
+ <% end %>
30
+ <%= beaming_mode %>
31
+ <%= partial %>
32
+ <%= part['music'] %>
33
+
34
+ <% if end_barline %>
35
+ \bar "<%= end_barline %>"
36
+ <% end %>
37
+ }
38
+ }
39
+
40
+ <% if part['lyrics'] %>
41
+ \addlyrics {
42
+ <%= part['lyrics'] %>
43
+ }
44
+ <% end %>
45
+
46
+ <% if part['lyrics2'] %>
47
+ \addlyrics {
48
+ <%= part['lyrics2'] %>
49
+ }
50
+ <% end %>
51
+
52
+ <% if part['figures'] %>
53
+ \figures { <%= part['figures'] %> }
54
+ <% end %>
55
+ >>
@@ -0,0 +1,22 @@
1
+ require 'erb'
2
+
3
+ module Lydown
4
+ module Templates
5
+ TEMPLATES_DIR = File.join(File.dirname(__FILE__), 'templates')
6
+
7
+ @@templates = {}
8
+
9
+ def self.render(name, ctx, locals = {})
10
+ _binding = ctx.respond_to?(:template_binding) ? ctx.template_binding(locals) : binding
11
+ template(name).result(_binding)
12
+ end
13
+
14
+ def self.template(name)
15
+ @@templates[name] ||= load_template(name)
16
+ end
17
+
18
+ def self.load_template(name)
19
+ ERB.new IO.read(File.join(TEMPLATES_DIR, "#{name}.erb")), 0, '<>'
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,3 @@
1
+ module Lydown
2
+ VERSION = "0.3.0"
3
+ end
@@ -0,0 +1,192 @@
1
+ require 'lydown/core_ext'
2
+ require 'lydown/templates'
3
+
4
+ require 'pp'
5
+
6
+ module Lydown
7
+ # Work is a virtual lilypond document. It can contain multiple movements,
8
+ # and each movement can contain multiple parts. Each part can contain multiple
9
+ # streams: music, lyrics, figured bass.
10
+ #
11
+ # A Work instance is created in order to translate lydown code into a
12
+ # virtual lilypond document, and then render it. The actual rendering may
13
+ # include all of the streams in the document, or only a selection,such as a
14
+ # specific movement, a specific part, or a specific stream type.
15
+ class Work
16
+ attr_accessor :context
17
+
18
+ def initialize(opts = {})
19
+ @context = {}.deep!
20
+ reset_context(:work)
21
+
22
+ opts.each {|k, v| @context[k] = v}
23
+
24
+ process_work_files if opts[:path]
25
+ end
26
+
27
+ def reset_context(mode)
28
+ case mode
29
+ when :work, :movement
30
+ @context[:time] = '4/4'
31
+ @context[:cadenza_mode] = nil
32
+ @context[:key] = 'c major'
33
+ @context[:pickup] = nil
34
+ @context[:beaming] = nil
35
+ @context[:end_barline] = nil
36
+ @context[:part] = nil
37
+ @context['process/duration_values'] = ['4']
38
+ @context['process/running_values'] = []
39
+ @context['process/last_value'] = nil
40
+ @context['process/last_figures_value'] = nil
41
+ when :part
42
+ @context['process/duration_values'] = ['4']
43
+ @context['process/running_values'] = []
44
+ @context['process/last_value'] = nil
45
+ @context['process/last_figures_value'] = nil
46
+ end
47
+ end
48
+
49
+ # Used to bind to instance when rendering templates
50
+ def template_binding(locals = {})
51
+ b = binding
52
+ locals.each {|k, v| b.local_variable_set(k.to_sym, v)}
53
+ b
54
+ end
55
+
56
+ # translate a lydown stream into lilypond
57
+ def process(lydown_stream)
58
+ lydown_stream.each_with_index do |e, idx|
59
+ if e[:type]
60
+ Lydown::Rendering.translate(self, e, lydown_stream, idx)
61
+ else
62
+ raise LydownError, "Invalid lydown stream event: #{e.inspect}"
63
+ end
64
+ end
65
+ end
66
+
67
+ def emit(stream_type, *content)
68
+ stream = current_stream(stream_type)
69
+
70
+ content.each {|c| stream << c}
71
+ end
72
+
73
+ def current_stream(type)
74
+ movement = @context[:movement]
75
+ part = @context[:part]
76
+ path = "movements/#{movement}/parts/#{part}/#{type}"
77
+ @context[path] ||= ''
78
+ end
79
+
80
+ def to_lilypond(opts = {})
81
+ @context['render_opts'] = opts
82
+ ly_code = ''
83
+
84
+ if opts[:stream_path]
85
+ unless @context[opts[:stream_path]]
86
+ raise LydownError, "Invalid stream path #{opts[:stream_path].inspect}"
87
+ end
88
+ @context[opts[:stream_path]].strip
89
+ else
90
+ @original_context = @context
91
+ begin
92
+ @context = filter_context(opts)
93
+ Lydown::Templates.render(:lilypond_doc, self)
94
+ ensure
95
+ @context = @original_context
96
+ end
97
+ end
98
+ end
99
+
100
+ def filter_context(opts = {})
101
+ filtered = @context.deep_clone
102
+
103
+ # delete default movement if other movements are present
104
+ if filtered['movements'].size > 1
105
+ filtered['movements'].delete('')
106
+ end
107
+
108
+ if opts[:movements]
109
+ opts[:movements] = [opts[:movements]] unless opts[:movements].is_a?(Array)
110
+ filtered['movements'].select! do |name, m|
111
+ opts[:movements].include?(name.to_s)
112
+ end
113
+ end
114
+
115
+ if opts[:parts]
116
+ opts[:parts] = [opts[:parts]] unless opts[:parts].is_a?(Array)
117
+ end
118
+ filtered['movements'].each do |name, m|
119
+ # delete default part if other parts are present
120
+ if m['parts'].size > 1
121
+ m['parts'].delete('')
122
+ end
123
+
124
+ if opts[:parts]
125
+ m['parts'].select! do |pname, p|
126
+ opts[:parts].include?(pname.to_s)
127
+ end
128
+ end
129
+ end
130
+
131
+ filtered
132
+ end
133
+
134
+ def compile(opts = {})
135
+ code = to_lilypond(opts)
136
+
137
+ Lydown::Lilypond.compile(code, opts)
138
+ end
139
+
140
+ def [](path)
141
+ context[path]
142
+ end
143
+
144
+ def []=(path, value)
145
+ context[path] = value
146
+ end
147
+
148
+ def process_work_files
149
+ path = @context[:path]
150
+ path += '.ld' if File.file?(path + '.ld')
151
+
152
+ if File.file?(path)
153
+ process_lydown_file(path)
154
+ elsif File.directory?(path)
155
+ process_directory(path)
156
+ else
157
+ raise LydownError, "Could not read #{path}"
158
+ end
159
+ end
160
+
161
+ DEFAULT_BASENAMES = %w{work movement}
162
+
163
+ def process_directory(path, recursive = true)
164
+ # process work code
165
+ process_lydown_file(File.join(path, 'work.ld'))
166
+
167
+ # process movement specific code
168
+ process_lydown_file(File.join(path, 'movement.ld'))
169
+
170
+ # Iterate over sorted directory entries
171
+ Dir["#{path}/*"].entries.sort.each do |entry|
172
+ if File.file?(entry) && (entry =~ /\.ld$/)
173
+ basename = File.basename(entry, '.*')
174
+ unless DEFAULT_BASENAMES.include?(basename)
175
+ part_code = [{type: :setting, key: 'part', value: basename}]
176
+ lydown_code = part_code + LydownParser.parse(IO.read(entry))
177
+ process(lydown_code)
178
+ end
179
+ elsif File.directory?(entry) && recursive
180
+ basename = File.basename(entry)
181
+ # set movement
182
+ process([{type: :setting, key: 'movement', value: basename}])
183
+ process_directory(entry, false)
184
+ end
185
+ end
186
+ end
187
+
188
+ def process_lydown_file(path)
189
+ process LydownParser.parse(IO.read(path)) if File.file?(path)
190
+ end
191
+ end
192
+ end
data/lib/lydown.rb ADDED
@@ -0,0 +1,11 @@
1
+ require 'rubygems'
2
+
3
+ module Lydown; end
4
+
5
+ require 'lydown/core_ext'
6
+ require 'lydown/errors'
7
+ require 'lydown/parsing'
8
+ require 'lydown/templates'
9
+ require 'lydown/rendering'
10
+ require 'lydown/lilypond'
11
+ require 'lydown/work'
metadata ADDED
@@ -0,0 +1,84 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: lydown
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.3.0
5
+ platform: ruby
6
+ authors:
7
+ - Sharon Rosner
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-05-21 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: treetop
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.6'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.6'
27
+ description: 'Lydown '
28
+ email: ciconia@gmail.com
29
+ executables:
30
+ - lydown
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - LICENSE
35
+ - README.md
36
+ - bin/lydown
37
+ - lib/lydown.rb
38
+ - lib/lydown/core_ext.rb
39
+ - lib/lydown/errors.rb
40
+ - lib/lydown/lilypond.rb
41
+ - lib/lydown/parsing.rb
42
+ - lib/lydown/parsing/lydown.treetop
43
+ - lib/lydown/parsing/nodes.rb
44
+ - lib/lydown/rendering.rb
45
+ - lib/lydown/rendering/base.rb
46
+ - lib/lydown/rendering/comments.rb
47
+ - lib/lydown/rendering/defaults.yml
48
+ - lib/lydown/rendering/figures.rb
49
+ - lib/lydown/rendering/lyrics.rb
50
+ - lib/lydown/rendering/movement.rb
51
+ - lib/lydown/rendering/music.rb
52
+ - lib/lydown/rendering/settings.rb
53
+ - lib/lydown/rendering/staff.rb
54
+ - lib/lydown/templates.rb
55
+ - lib/lydown/templates/lilypond_doc.erb
56
+ - lib/lydown/templates/movement.erb
57
+ - lib/lydown/templates/part.erb
58
+ - lib/lydown/version.rb
59
+ - lib/lydown/work.rb
60
+ homepage: http://github.com/ciconia/lydown
61
+ licenses:
62
+ - MIT
63
+ metadata: {}
64
+ post_install_message:
65
+ rdoc_options: []
66
+ require_paths:
67
+ - lib
68
+ required_ruby_version: !ruby/object:Gem::Requirement
69
+ requirements:
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ version: '0'
73
+ required_rubygems_version: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ requirements: []
79
+ rubyforge_project:
80
+ rubygems_version: 2.4.6
81
+ signing_key:
82
+ specification_version: 4
83
+ summary: Lydown is a language for music notation
84
+ test_files: []