lydown 0.7.1 → 0.7.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: 8f9e00d9938576429da9646dc782f2451c66afa9
4
- data.tar.gz: 3fe22010c7e1928c74a5278eb659dc78922a53a8
3
+ metadata.gz: 2945708b90bba8a47e9c037ed6b58feee552c411
4
+ data.tar.gz: 3fab488b2070abaa55eccd5a2d1ee2af496419af
5
5
  SHA512:
6
- metadata.gz: f18283718262a5404cb6e78ba0c155c3c0f750eaf3ddf47b3f5e6b460836980fb9019e2146bb093aa662e1da25625880fb935479e9766a47f565dd4107300516
7
- data.tar.gz: 86b12d5d519691dc54f18fcfd061eb2d26a1d403780b3e8b5d800e32278bb78250841c818f1a76d7353fd5deffc99642d2eecf960c756205b06c7389a2e72650
6
+ metadata.gz: c9a16ab91b2118d2ceed5791caa10319fac63e38bd09da38e19fb57ba52ab5ad6b3db857c811211a0e8f5d167d0f0e5b841aee06f0bb607df4cdba0cbd794b97
7
+ data.tar.gz: 25df40e9a348873a1da26969c8f8275e7f806ff4f5386657c3a1eba4acdbd7d84f4c687eb5653867973dd656acf4b9eeb59a4ce9e9da9d73894d09a609ae7123
@@ -72,7 +72,8 @@ module Lydown::CLI::Compiler
72
72
  unless File.file?(filename)
73
73
  filename = "#{opts[:output_target]}-page1.#{opts[:format]}"
74
74
  end
75
-
75
+
76
+ # Mac OSX specific probably
76
77
  system("open #{filename}")
77
78
  end
78
79
  end
@@ -42,6 +42,9 @@ module Lydown::CLI::Diff
42
42
 
43
43
  set_cached_content(path, new_version)
44
44
 
45
+ first += 1 if first
46
+ last += 1 if last
47
+
45
48
  first..last
46
49
  rescue => e
47
50
  STDERR << e.message
@@ -20,16 +20,18 @@ module Lydown::CLI::Proofing
20
20
 
21
21
  dw.reset(true)
22
22
  dw.add_observer do |*args|
23
- t = Time.now.strftime("%Y-%m-%d %H:%M:%S")
24
23
  args.each do |e|
25
24
  if e.type = :modified
26
25
  path = File.expand_path(e.path)
27
26
  if path =~ /^#{File.expand_path(source)}\/(.+)/
28
27
  path = $1
29
28
  end
30
- puts "[#{t}] Changed: #{path}"
31
29
  last_proof_path = e.path unless File.basename(e.path) == 'movement.ld'
32
- process(opts.deep_merge opts_for_path(last_proof_path, opts)) if last_proof_path
30
+ if last_proof_path
31
+ file_opts = opts.deep_merge opts_for_path(last_proof_path, opts)
32
+ file_opts[:base_path] = path
33
+ process(file_opts)
34
+ end
33
35
  end
34
36
  end
35
37
  end
@@ -44,12 +46,6 @@ module Lydown::CLI::Proofing
44
46
  def globs(path)
45
47
  Dir.chdir(path) do
46
48
  dirs = Dir['*'].select { |x| File.directory?(x) }
47
- # exclude _ly, _pdf, _midi dirs
48
- # ['ly_dir', 'pdf_dir', 'midi_dir'].map {|d| $config[d]}.each do |d|
49
- # if d =~ /^\.\/(.*)/
50
- # dirs -= [$1]
51
- # end
52
- # end
53
49
  end
54
50
 
55
51
  dirs = dirs.map { |x| "#{x}/**/*" }
@@ -87,9 +83,9 @@ module Lydown::CLI::Proofing
87
83
  end
88
84
 
89
85
  def process(opts)
90
- if opts[:line_range] == (nil..nil)
91
- puts "No change detected"
92
- else
86
+ if opts[:line_range] != (nil..nil)
87
+ t = Time.now.strftime("%H:%M:%S")
88
+ puts "[#{t}] Changed: #{opts[:base_path]} (lines #{opts[:line_range].inspect})"
93
89
  Lydown::CLI::Compiler.process(opts)
94
90
  end
95
91
  end
@@ -1,3 +1,5 @@
1
+ require 'escape_utils'
2
+
1
3
  class Hash
2
4
  # Merges self with another hash, recursively.
3
5
  #
@@ -137,6 +139,33 @@ class String
137
139
  end
138
140
  }
139
141
  end
142
+
143
+ def calculate_line_indexes
144
+ i = -1
145
+ indexes = {0 => 0}
146
+ line = 1
147
+ while i = index("\n", i + 1)
148
+ indexes[line] = i + 1 # first character after line break
149
+ line += 1
150
+ end
151
+ indexes
152
+ end
153
+
154
+ def find_line_and_column(index)
155
+ @line_indexes ||= calculate_line_indexes
156
+ line = @line_indexes.reverse_each {|l, i| break l if i <= index}
157
+
158
+ # return line and column
159
+ if line.nil?
160
+ [nil, nil]
161
+ else
162
+ [(line + 1), (index - @line_indexes[line] + 1)]
163
+ end
164
+ end
165
+
166
+ def uri_escape
167
+ EscapeUtils.escape_uri(self)
168
+ end
140
169
  end
141
170
 
142
171
  class Fixnum
@@ -49,9 +49,9 @@ module Lydown
49
49
  # Run lilypond, pipe source into its STDIN, and capture its STDERR
50
50
  cmd = 'lilypond -lERROR '
51
51
  cmd << "-o #{opts[:output_filename]} "
52
+ cmd << "-dno-point-and-click "
52
53
  cmd << "--#{opts[:format]} " if opts[:format]
53
54
  cmd << '-s - 2>&1'
54
- # cmd << "-s #{ly_path} 2>&1"
55
55
 
56
56
  err_info = ''
57
57
  IO.popen(cmd, 'r+') do |f|
@@ -15,7 +15,10 @@ class LydownParser
15
15
  STDERR.puts error_msg
16
16
  raise LydownError, error_msg
17
17
  else
18
- ast.to_stream
18
+ stream = []
19
+ # insert source ref event into stream if we have a filename ref
20
+ stream << {type: :source_ref}.merge(opts) if opts[:filename]
21
+ ast.to_stream(stream, opts)
19
22
  end
20
23
  end
21
24
 
@@ -11,7 +11,8 @@ grammar Lydown
11
11
  '=music' white_space? [\n] music ([\n] !stream_breaker music)*
12
12
  end
13
13
  rule lyrics_stream
14
- '=lyrics' stream_idx? white_space? [\n] lyrics_content ([\n] !stream_breaker lyrics_content)* <Lyrics>
14
+ '=lyrics' stream_idx? white_space? [\n] lyrics_content
15
+ ([\n] !stream_breaker lyrics_content)* <Lyrics>
15
16
  end
16
17
  rule stream_breaker
17
18
  stream_switch / stream_breaking_setting
@@ -29,7 +30,8 @@ grammar Lydown
29
30
  [^\n]* <CommentContent>
30
31
  end
31
32
  rule setting
32
- white_space? '-' white_space* setting_key ':' setting_value comment? <Setting>
33
+ white_space? '-' white_space* setting_key ':' setting_value
34
+ comment? <Setting>
33
35
  end
34
36
  rule setting_key
35
37
  [a-z0-9_]+ <Setting::Key>
@@ -44,13 +46,12 @@ grammar Lydown
44
46
  [ \t]+
45
47
  end
46
48
  rule event
47
- (inline_command / inline_lyrics / voice_selector / barline / grace_duration / duration /
48
- chord / note / standalone_figures / rest / silence / phrasing / tie) white_space*
49
+ (inline_command / inline_lyrics / voice_selector / barline / source_ref /
50
+ grace_duration / duration / chord / note / standalone_figures / rest /
51
+ silence / phrasing / tie) white_space*
49
52
  end
50
53
  rule barline
51
54
  ('?|' / ':|][|:' / '[|:' / ':|]' / [\|\.\:]+) <Barline>
52
- # ('|' / '.' / '||' / '.|' / '..' / '|.|' / '|.' /
53
- # '.|') <Barline>
54
55
  end
55
56
  rule duration
56
57
  tuplet_value / duration_value / duration_macro
@@ -83,7 +84,8 @@ grammar Lydown
83
84
  (macro_name / macro_event*) <DurationMacroExpression>
84
85
  end
85
86
  rule macro_event
86
- (duration / note_placeholder / rest / silence / phrasing / tie) white_space*
87
+ (duration / note_placeholder / rest / silence /
88
+ phrasing / tie) white_space*
87
89
  end
88
90
  rule macro_name
89
91
  [a-zA-Z_] [a-zA-Z0-9_]*
@@ -191,4 +193,13 @@ grammar Lydown
191
193
  rule voice_selector
192
194
  [1234u] ':' <VoiceSelector>
193
195
  end
196
+ rule source_ref
197
+ '{' source_line ':' source_column '}' <SourceRef>
198
+ end
199
+ rule source_line
200
+ [\d]+ <SourceRef::Line>
201
+ end
202
+ rule source_column
203
+ [\d]+ <SourceRef::Column>
204
+ end
194
205
  end
@@ -1,22 +1,44 @@
1
1
  module Lydown::Parsing
2
2
  module Root
3
- def _to_stream(element, stream)
3
+ def _to_stream(element, stream, opts)
4
4
  if element.elements
5
5
  element.elements.each do |e|
6
- e.respond_to?(:to_stream) ? e.to_stream(stream) : _to_stream(e, stream)
6
+ e.respond_to?(:to_stream) ?
7
+ e.to_stream(stream, opts) :
8
+ _to_stream(e, stream, opts)
7
9
  end
8
10
  end
9
11
  stream
10
12
  end
11
-
12
- def to_stream(stream = [])
13
- _to_stream(self, stream)
13
+
14
+ def to_stream(stream = [], opts = {})
15
+ _to_stream(self, stream, opts)
14
16
  stream
15
17
  end
18
+
19
+ def event_hash(stream, opts, hash = {})
20
+ if source = opts[:source]
21
+ last = stream.last
22
+ if last && last[:type] == :source_ref && last[:line]
23
+ line, column = last[:line], last[:column]
24
+ else
25
+ line, column = source.find_line_and_column(interval.first)
26
+ end
27
+
28
+ hash.merge({
29
+ filename: opts[:filename],
30
+ source: source,
31
+ line: line,
32
+ column: column
33
+ })
34
+ else
35
+ hash
36
+ end
37
+ end
16
38
  end
17
39
 
18
40
  module CommentContent
19
- def to_stream(stream)
41
+ def to_stream(stream, opts)
20
42
  stream << {type: :comment, content: text_value.strip}
21
43
  end
22
44
  end
@@ -24,28 +46,30 @@ module Lydown::Parsing
24
46
  module Setting
25
47
  include Root
26
48
 
27
- def to_stream(stream)
49
+ def to_stream(stream, opts)
28
50
  level = (text_value =~ /^([\s]+)/) ? ($1.length / 2) : 0
29
- @setting = {type: :setting, level: level}
30
- _to_stream(self, stream)
51
+ @setting = event_hash(stream, opts, {
52
+ type: :setting, level: level
53
+ })
54
+ _to_stream(self, stream, opts)
31
55
  end
32
-
56
+
33
57
  def setting
34
58
  @setting
35
59
  end
36
-
60
+
37
61
  def emit_setting(stream)
38
62
  stream << @setting
39
63
  end
40
64
 
41
65
  module Key
42
- def to_stream(stream)
66
+ def to_stream(stream, opts)
43
67
  parent.setting[:key] = text_value
44
68
  end
45
69
  end
46
70
 
47
71
  module Value
48
- def to_stream(stream)
72
+ def to_stream(stream, opts)
49
73
  parent.setting[:value] = text_value.strip
50
74
  parent.emit_setting(stream)
51
75
  end
@@ -53,13 +77,19 @@ module Lydown::Parsing
53
77
  end
54
78
 
55
79
  module DurationValue
56
- def to_stream(stream)
57
- stream << {type: :duration, value: text_value}
80
+ include Root
81
+
82
+ def to_stream(stream, opts)
83
+ stream << event_hash(stream, opts, {
84
+ type: :duration, value: text_value
85
+ })
58
86
  end
59
87
  end
60
88
 
61
89
  module TupletValue
62
- def to_stream(stream)
90
+ include Root
91
+
92
+ def to_stream(stream, opts)
63
93
  if text_value =~ /^(\d+)%((\d+)\/(\d+))?$/
64
94
  value, fraction, group_length = $1, $2, $4
65
95
  unless fraction
@@ -67,26 +97,30 @@ module Lydown::Parsing
67
97
  group_length = '2'
68
98
  end
69
99
 
70
- stream << {
100
+ stream << event_hash(stream, opts, {
71
101
  type: :tuplet_duration,
72
102
  value: value,
73
103
  fraction: fraction,
74
104
  group_length: group_length
75
- }
105
+ })
76
106
  end
77
107
  end
78
108
  end
79
109
 
80
110
  module GraceDuration
111
+ include Root
112
+
81
113
  GRACE_KIND = {
82
114
  nil => :grace,
83
115
  '/' => :acciaccatura,
84
116
  '^' => :appoggiatura
85
117
  }
86
118
 
87
- def to_stream(stream)
119
+ def to_stream(stream, opts)
88
120
  if text_value =~ /^\$([\/\^])?(\d+)$/
89
- stream << {type: :grace, value: $2, kind: GRACE_KIND[$1]}
121
+ stream << event_hash(stream, opts, {
122
+ type: :grace, value: $2, kind: GRACE_KIND[$1]
123
+ })
90
124
  end
91
125
  end
92
126
  end
@@ -94,14 +128,16 @@ module Lydown::Parsing
94
128
  module Note
95
129
  include Root
96
130
 
97
- def to_stream(stream)
98
- note = {type: :note, raw: text_value}
99
- _to_stream(self, note)
131
+ def to_stream(stream, opts)
132
+ note = event_hash(stream, opts, {
133
+ type: :note, raw: text_value
134
+ })
135
+ _to_stream(self, note, opts)
100
136
  stream << note
101
137
  end
102
138
 
103
139
  module Head
104
- def to_stream(note)
140
+ def to_stream(note, opts)
105
141
  # remove octave marks from note head (this is only in case the order
106
142
  # accidental-octave was reversed)
107
143
  head = text_value.gsub(/[',]+/) {|m| note[:octave] = m; ''}
@@ -110,19 +146,19 @@ module Lydown::Parsing
110
146
  end
111
147
 
112
148
  module Octave
113
- def to_stream(note)
149
+ def to_stream(note, opts)
114
150
  note[:octave] = text_value
115
151
  end
116
152
  end
117
153
 
118
154
  module AccidentalFlag
119
- def to_stream(note)
155
+ def to_stream(note, opts)
120
156
  note[:accidental_flag] = text_value
121
157
  end
122
158
  end
123
159
 
124
160
  module Expression
125
- def to_stream(note)
161
+ def to_stream(note, opts)
126
162
  note[:expressions] ||= []
127
163
  note[:expressions] << text_value
128
164
  end
@@ -132,15 +168,17 @@ module Lydown::Parsing
132
168
  module Chord
133
169
  include Root
134
170
 
135
- def to_stream(stream)
136
- chord = {type: :chord, notes: []}
137
- _to_stream(self, chord[:notes])
171
+ def to_stream(stream, opts)
172
+ chord = event_hash(stream, opts, {
173
+ type: :chord, notes: []
174
+ })
175
+ _to_stream(self, chord[:notes], opts)
138
176
  stream << chord
139
177
  end
140
178
  end
141
179
 
142
180
  module FiguresComponent
143
- def to_stream(note)
181
+ def to_stream(note, opts)
144
182
  note[:figures] ||= []
145
183
  note[:figures] << text_value
146
184
  end
@@ -149,47 +187,47 @@ module Lydown::Parsing
149
187
  module StandAloneFigures
150
188
  include Root
151
189
 
152
- def to_stream(stream)
190
+ def to_stream(stream, opts)
153
191
  note = {type: :stand_alone_figures}
154
- _to_stream(self, note)
192
+ _to_stream(self, note, opts)
155
193
  stream << note
156
194
  end
157
195
  end
158
196
 
159
197
  module Phrasing
160
198
  module BeamOpen
161
- def to_stream(stream)
199
+ def to_stream(stream, opts)
162
200
  stream << {type: :beam_open}
163
201
  end
164
202
  end
165
203
 
166
204
  module BeamClose
167
- def to_stream(stream)
205
+ def to_stream(stream, opts)
168
206
  stream << {type: :beam_close}
169
207
  end
170
208
  end
171
209
 
172
210
  module SlurOpen
173
- def to_stream(stream)
211
+ def to_stream(stream, opts)
174
212
  stream << {type: :slur_open}
175
213
  end
176
214
  end
177
215
 
178
216
  module SlurClose
179
- def to_stream(stream)
217
+ def to_stream(stream, opts)
180
218
  stream << {type: :slur_close}
181
219
  end
182
220
  end
183
221
  end
184
222
 
185
223
  module Tie
186
- def to_stream(stream)
224
+ def to_stream(stream, opts)
187
225
  stream << {type: :tie}
188
226
  end
189
227
  end
190
228
 
191
229
  module ShortTie
192
- def to_stream(stream)
230
+ def to_stream(stream, opts)
193
231
  stream << {type: :short_tie}
194
232
  end
195
233
  end
@@ -197,40 +235,50 @@ module Lydown::Parsing
197
235
  module Rest
198
236
  include Root
199
237
 
200
- def to_stream(stream)
201
- rest = {type: :rest, raw: text_value, head: text_value[0]}
238
+ def to_stream(stream, opts)
239
+ rest = event_hash(stream, opts, {
240
+ type: :rest, raw: text_value, head: text_value[0]
241
+ })
202
242
  if text_value =~ /^R(\*([0-9]+))?$/
203
243
  rest[:multiplier] = $2 || '1'
204
244
  end
205
245
 
206
- _to_stream(self, rest)
246
+ _to_stream(self, rest, opts)
207
247
 
208
248
  stream << rest
209
249
  end
210
250
  end
211
251
 
212
252
  module Silence
213
- def to_stream(stream)
214
- stream << {type: :silence, raw: text_value, head: text_value[0]}
253
+ include Root
254
+
255
+ def to_stream(stream, opts)
256
+ stream << event_hash(stream, opts, {
257
+ type: :silence, raw: text_value, head: text_value[0]
258
+ })
215
259
  end
216
260
  end
217
261
 
218
262
  module DurationMacroExpression
219
- def to_stream(stream)
220
- stream << {type: :duration_macro, macro: text_value}
263
+ include Root
264
+
265
+ def to_stream(stream, opts)
266
+ stream << event_hash(stream, opts, {
267
+ type: :duration_macro, macro: text_value
268
+ })
221
269
  end
222
270
  end
223
271
 
224
272
  module Lyrics
225
273
  include Root
226
- def to_stream(stream)
274
+ def to_stream(stream, opts)
227
275
  o = {type: :lyrics}
228
- _to_stream(self, o)
276
+ _to_stream(self, o, opts)
229
277
  stream << o
230
278
  end
231
279
 
232
280
  module Content
233
- def to_stream(o)
281
+ def to_stream(o, opts)
234
282
  if o[:content]
235
283
  o[:content] << ' ' << text_value
236
284
  else
@@ -240,7 +288,7 @@ module Lydown::Parsing
240
288
  end
241
289
 
242
290
  module QuotedContent
243
- def to_stream(o)
291
+ def to_stream(o, opts)
244
292
  if text_value =~ /^"(.+)"$/
245
293
  content = $1
246
294
  else
@@ -257,7 +305,7 @@ module Lydown::Parsing
257
305
  end
258
306
 
259
307
  module StreamIndex
260
- def to_stream(o)
308
+ def to_stream(o, opts)
261
309
  idx = (text_value =~ /\(([\d]+)\)/) && $1.to_i
262
310
  if idx.nil?
263
311
  raise LydownError, "Invalid stream index (#{text_value.inspect})"
@@ -267,24 +315,27 @@ module Lydown::Parsing
267
315
  end
268
316
 
269
317
  module Barline
270
- def to_stream(stream)
318
+ def to_stream(stream, opts)
271
319
  stream << {type: :barline, barline: text_value}
272
320
  end
273
321
  end
274
322
 
275
323
  module Command
276
324
  include Root
277
- def to_stream(stream)
278
- cmd = {type: :command, raw: text_value}
325
+
326
+ def to_stream(stream, opts)
327
+ cmd = event_hash(stream, opts, {
328
+ type: :command, raw: text_value
329
+ })
279
330
  cmd[:once] = true if text_value =~ /^\\\!/
280
- _to_stream(self, cmd)
331
+ _to_stream(self, cmd, opts)
281
332
  stream << cmd
282
333
  end
283
334
 
284
335
  SETTING_KEYS = %w{time key clef}
285
336
 
286
337
  module Key
287
- def to_stream(cmd)
338
+ def to_stream(cmd, opts)
288
339
  cmd[:key] = text_value
289
340
  if SETTING_KEYS.include?(text_value)
290
341
  cmd[:type] = :setting
@@ -293,7 +344,7 @@ module Lydown::Parsing
293
344
  end
294
345
 
295
346
  module Argument
296
- def to_stream(cmd)
347
+ def to_stream(cmd, opts)
297
348
  if text_value =~ /^"(.+)"$/
298
349
  value = $1.unescape
299
350
  else
@@ -311,9 +362,30 @@ module Lydown::Parsing
311
362
  end
312
363
 
313
364
  module VoiceSelector
314
- def to_stream(stream)
365
+ def to_stream(stream, opts)
315
366
  voice = (text_value =~ /^([1234])/) && $1.to_i
316
367
  stream << {type: :voice_select, voice: voice}
317
368
  end
318
369
  end
370
+
371
+ module SourceRef
372
+ include Root
373
+ def to_stream(stream, opts)
374
+ ref = {type: :source_ref, raw: text_value}
375
+ _to_stream(self, ref, opts)
376
+ stream << ref
377
+ end
378
+
379
+ module Line
380
+ def to_stream(ref, opts)
381
+ ref[:line] = text_value.to_i
382
+ end
383
+ end
384
+
385
+ module Column
386
+ def to_stream(ref, opts)
387
+ ref[:column] = text_value.to_i
388
+ end
389
+ end
390
+ end
319
391
  end
@@ -10,6 +10,8 @@ require 'lydown/rendering/staff'
10
10
  require 'lydown/rendering/movement'
11
11
  require 'lydown/rendering/command'
12
12
  require 'lydown/rendering/voices'
13
+ require 'lydown/rendering/source_ref'
14
+ require 'lydown/rendering/skipping'
13
15
 
14
16
  require 'yaml'
15
17
 
@@ -4,12 +4,21 @@ module Lydown::Rendering
4
4
 
5
5
  def translate
6
6
  if @work['process/duration_macro']
7
- add_macro_event(@event[:raw])
7
+ add_macro_event(@event[:raw] || cmd_to_lydown(@event))
8
8
  else
9
9
  once = @event[:once] ? '\once ' : ''
10
10
  cmd = "#{once}\\#{@event[:key]} #{(@event[:arguments] || []).join(' ')} "
11
11
  @work.emit(:music, cmd)
12
12
  end
13
13
  end
14
+
15
+ def cmd_to_lydown(event)
16
+ cmd = "\\#{event[:key]}"
17
+ if event[:arguments]
18
+ cmd << ":"
19
+ cmd << event[:arguments].map {|a| a.inspect}.join(':')
20
+ end
21
+ cmd
22
+ end
14
23
  end
15
24
  end
@@ -106,6 +106,11 @@ module Lydown::Rendering
106
106
  else
107
107
  @work['process/last_value'] = value
108
108
  end
109
+
110
+ if event[:line] && @work['options/proof_mode']
111
+ @work.emit(event[:stream] || :music, note_event_url_link(event))
112
+ # @work.emit(event[:stream] || :music, "%{#{event[:line]}:#{event[:column]}%}")
113
+ end
109
114
 
110
115
  code = lilypond_note(event, options.merge(value: value))
111
116
  @work.emit(event[:stream] || :music, code)
@@ -219,7 +224,9 @@ module Lydown::Rendering
219
224
  @work['process/macro_group'] ||= @work['process/duration_macro'].clone
220
225
  underscore_count = 0
221
226
 
222
- lydown_note = "%s%s%s%s%s%s%s" % [
227
+ lydown_note = "{%d:%d}%s%s%s%s%s%s%s" % [
228
+ event[:line] || 0,
229
+ event[:column] || 0,
223
230
  lydown_phrasing_open(event),
224
231
  event[:head], event[:octave], event[:accidental_flag],
225
232
  lydown_phrasing_close(event),
@@ -240,7 +247,10 @@ module Lydown::Rendering
240
247
 
241
248
  # if group is complete, compile it just like regular code
242
249
  unless @work['process/macro_group'].include?('_')
243
- code = LydownParser.parse(@work['process/macro_group'])
250
+ code = LydownParser.parse(@work['process/macro_group'], {
251
+ filename: event[:filename],
252
+ source: event[:source]
253
+ })
244
254
 
245
255
  # stash macro
246
256
  macro = @work['process/duration_macro']
@@ -312,5 +322,20 @@ module Lydown::Rendering
312
322
  gsub(/__([^_]+)__/) {|m| "\\bold { #{$1} }" }.
313
323
  gsub(/_([^_]+)_/) {|m| "\\italic { #{$1} }" }
314
324
  end
325
+
326
+ TEXTMATE_URL = "txmt://open?url=file://%s&line=%d&column=%d"
327
+
328
+ ADD_LINK_COMMAND = '\once \override NoteHead.after-line-breaking =
329
+ #(add-link "%s") '
330
+
331
+ def note_event_url_link(event)
332
+ url = TEXTMATE_URL % [
333
+ File.expand_path(event[:filename]).uri_escape,
334
+ event[:line],
335
+ event[:column]
336
+ ]
337
+
338
+ ADD_LINK_COMMAND % [url]
339
+ end
315
340
  end
316
341
  end
@@ -0,0 +1,49 @@
1
+ module Lydown::Rendering
2
+ class << self
3
+ SKIP_ON_CMD = {type: :command, key: 'set', arguments: ['Score.skipTypesetting = ##t']}
4
+ SKIP_OFF_CMD = {type: :command, key: 'set', arguments: ['Score.skipTypesetting = ##f']}
5
+
6
+ BARLINE = {type: :barline, barline: '|'}
7
+ BAR_NUMBERS_CMD = {type: :command, key: 'set', arguments: ['Score.barNumberVisibility = #all-bar-numbers-visible']}
8
+
9
+ HIGHLIGHT_NOTES_CMD = {type: :command, key: 'override', arguments: ['NoteHead.color = #red']}
10
+ NORMAL_NOTES_CMD = {type: :command, key: 'override', arguments: ['NoteHead.color = #black']}
11
+
12
+ def insert_skip_markers(stream, line_range)
13
+ # find indexes of first and last changed lines
14
+ changed_first_idx = find_line_idx(stream, line_range.first)
15
+ changed_last_idx = find_line_idx(stream, line_range.last, true)
16
+
17
+ # find index of first line to include
18
+ start_line = line_range.first - 2; start_line = 0 if start_line < 0
19
+ start_idx = find_line_idx(stream, start_line)
20
+
21
+ if changed_last_idx
22
+ stream.insert(changed_last_idx + 1, NORMAL_NOTES_CMD)
23
+ end
24
+
25
+ if changed_first_idx
26
+ stream.insert(changed_first_idx, BARLINE)
27
+ stream.insert(changed_first_idx, BAR_NUMBERS_CMD)
28
+ stream.insert(changed_first_idx, HIGHLIGHT_NOTES_CMD)
29
+ end
30
+
31
+ if start_line > 0 && start_idx
32
+ stream.insert(start_idx, SKIP_OFF_CMD)
33
+ stream.insert(0, SKIP_ON_CMD)
34
+ end
35
+ end
36
+
37
+ # returns index of first event at or after specified line
38
+ def find_line_idx(stream, line, last = false)
39
+ if last
40
+ stream.reverse_each do |e|
41
+ return stream.index(e) if e[:line] && e[:line] <= line
42
+ end
43
+ nil
44
+ else
45
+ stream.index {|e| e[:line] && e[:line] >= line}
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,15 @@
1
+ module Lydown::Rendering
2
+ # SourceRef does nothing, it's only there to provide line, column references
3
+ # for notes in a macro group
4
+ class SourceRef < Base
5
+ def translate
6
+ return # unless @work['options/proof_mode']
7
+
8
+ fn = @event[:filename]
9
+ if fn && fn != @work['process/last_filename']
10
+ @work['process/last_filename'] = fn
11
+ @work.emit(@event[:stream] || :music, "%{::#{File.expand_path(fn)}%} ")
12
+ end
13
+ end
14
+ end
15
+ end
@@ -1,3 +1,3 @@
1
1
  module Lydown
2
- VERSION = "0.7.1"
2
+ VERSION = "0.7.2"
3
3
  end
data/lib/lydown/work.rb CHANGED
@@ -246,46 +246,20 @@ module Lydown
246
246
  end
247
247
  end
248
248
 
249
- SKIP_ON = "\\set:\"Score.skipTypesetting = ##t\""
250
- SHOW_BAR_NUMBERS = "\\set:\"Score.barNumberVisibility = #all-bar-numbers-visible\" |"
251
- SKIP_OFF = "\\set:\"Score.skipTypesetting = ##f\""
252
-
253
- HIGHLIGHT = "\\large \\override:\"NoteHead.color = #red\""
254
- NORMAL = "\\large \\override:\"NoteHead.color = #black\""
255
-
256
- def insert_skip_markers(content, range)
257
- unless range.first.nil?
258
- lines = content.lines
259
- start = range.first - 2; start = 0 if start < 0
260
- stop = range.last + 2; stop = lines.size if stop > lines.size
261
-
262
- lines.insert(stop, "| #{SKIP_ON}")
263
- lines.insert(range.last + 1, NORMAL)
264
- if start > 0
265
- lines.insert(range.first, HIGHLIGHT)
266
- lines.insert(start, SHOW_BAR_NUMBERS)
267
- lines.insert(start, NORMAL)
268
- lines.insert(start, SKIP_OFF)
269
- lines.insert(0, SKIP_ON)
270
- else
271
- lines.insert(0, SHOW_BAR_NUMBERS)
272
- end
273
-
274
- lines.join("\n")
275
- else
276
- content
277
- end
278
- end
279
-
280
249
  def process_lydown_file(path, prefix = [], opts = {})
281
250
  return unless File.file?(path)
282
251
 
283
252
  content = IO.read(path)
253
+ stream = LydownParser.parse(content, {
254
+ filename: File.expand_path(path),
255
+ source: content
256
+ })
257
+
284
258
  if opts[:line_range]
285
- content = insert_skip_markers(content, opts[:line_range])
259
+ Lydown::Rendering.insert_skip_markers(stream, opts[:line_range])
286
260
  end
287
261
 
288
- process(prefix + LydownParser.parse(content))
262
+ process(prefix + stream)
289
263
  end
290
264
  end
291
265
  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.7.1
4
+ version: 0.7.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-07-01 00:00:00.000000000 Z
11
+ date: 2015-07-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: treetop
@@ -57,6 +57,8 @@ files:
57
57
  - lib/lydown/rendering/music.rb
58
58
  - lib/lydown/rendering/notes.rb
59
59
  - lib/lydown/rendering/settings.rb
60
+ - lib/lydown/rendering/skipping.rb
61
+ - lib/lydown/rendering/source_ref.rb
60
62
  - lib/lydown/rendering/staff.rb
61
63
  - lib/lydown/rendering/voices.rb
62
64
  - lib/lydown/templates.rb