lydown 0.7.0 → 0.7.1

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: d8be82e654bd57692d8e882f1c8643bd684d637c
4
- data.tar.gz: 80c45eb4a1a4c4eb26960356e01774150d0b2697
3
+ metadata.gz: 8f9e00d9938576429da9646dc782f2451c66afa9
4
+ data.tar.gz: 3fe22010c7e1928c74a5278eb659dc78922a53a8
5
5
  SHA512:
6
- metadata.gz: 755759c7dbc352e537743f8b829f35791297baa586a89a2e80cbd6fd98aef6a48cd54bb8f2d7c26c1aa8a4568701c69d5fdf117d56a271e9a1aebdf24aecbf0c
7
- data.tar.gz: e5e151f5f78d6b372ca5cf655aeba53dc68be083d6b34b160b0211c89a9c6765498db2878f093ebd7d3e1c9fdac9d3bd2da11ee955c43b768b944f72e81d9f8f
6
+ metadata.gz: f18283718262a5404cb6e78ba0c155c3c0f750eaf3ddf47b3f5e6b460836980fb9019e2146bb093aa662e1da25625880fb935479e9766a47f565dd4107300516
7
+ data.tar.gz: 86b12d5d519691dc54f18fcfd061eb2d26a1d403780b3e8b5d800e32278bb78250841c818f1a76d7353fd5deffc99642d2eecf960c756205b06c7389a2e72650
data/bin/lydown CHANGED
@@ -13,7 +13,7 @@ help = <<HELP
13
13
  Lydown is not lilypond
14
14
  HELP
15
15
 
16
- $options = {'format' => 'pdf'}
16
+ $options = {'format' => 'pdf'}.deep!
17
17
  opts = OptionParser.new do |opts|
18
18
  opts.banner = help
19
19
 
@@ -23,64 +23,64 @@ opts = OptionParser.new do |opts|
23
23
  end
24
24
 
25
25
  opts.on("-p", "--parts PART", "Parts (comma-separated)") do |v|
26
- $options["parts"] = v.split(',')
26
+ $options[:parts] = v.split(',')
27
27
  end
28
28
 
29
29
  opts.on("-m", "--mvts MVT", "Movements (comma-separated)") do |v|
30
- $options["movements"] = v.split(',')
30
+ $options[:movements] = v.split(',')
31
31
  end
32
32
 
33
33
  opts.on("--no-score", "Do not generate secore") do
34
- $options["no_score"] = true
34
+ $options[:no_score] = true
35
35
  end
36
36
 
37
37
  opts.on("-s", "--score", "Generate only score, no parts") do
38
- $options["score_only"] = true
38
+ $options[:score_only] = true
39
39
  end
40
40
 
41
41
  opts.on("-V", "--vocal", "Generate only vocal score") do
42
- $options["vocal_only"] = true
42
+ $options[:vocal_only] = true
43
43
  end
44
44
 
45
45
  opts.on("--ly", "Generate Lilypond file") do
46
- $options["format"] = 'ly'
46
+ $options[:format] = 'ly'
47
47
  end
48
48
 
49
49
  opts.on("--pdf", "Generate PDF file") do
50
- $options["format"] = 'pdf'
50
+ $options[:format] = 'pdf'
51
51
  end
52
52
 
53
53
  opts.on("--png", "Generate PNG file") do
54
- $options["format"] = 'png'
54
+ $options[:format] = 'png'
55
55
  end
56
56
 
57
57
  opts.on("-M", "--midi", "Generate midi file") do
58
- $options["format"] = 'midi'
59
- $options["score_only"] = true # implied
58
+ $options[:format] = 'midi'
59
+ $options[:score_only] = true # implied
60
60
  end
61
61
 
62
62
  opts.on("-P", "--proof", "Start proofing mode") do
63
- $options["proof_mode"] = true
63
+ $options[:open_target] = true
64
+ $options[:proof_mode] = true
64
65
  end
65
66
 
66
67
  opts.on("-O", "--open", "Open PDF/Midi file after processing") do
67
- $options["open_target"] = true
68
+ $options[:open_target] = true
68
69
  end
69
70
 
70
71
  opts.on("-o", "--output FILE", "Filename for output") do |v|
71
- $options["output_filename"] = v
72
+ $options[:output_filename] = v
72
73
  end
73
74
 
74
75
  opts.on("-W", "--work", "Create new work") do
75
- $options["gen"] = :work
76
+ $options[:gen] = :work
76
77
  end
77
78
  end
78
79
 
79
80
  opts.parse!
80
- $options.deep!
81
81
 
82
- if $options["gen"]
83
- # Ripple.generate($options["gen"], ARGV)
82
+ if $options[:gen]
83
+ # Ripple.generate($options[:gen], ARGV)
84
84
  exit
85
85
  end
86
86
 
@@ -91,26 +91,36 @@ if ARGV[0] == '-'
91
91
 
92
92
  # the output defaults to a file named lydown expect if the format is ly.
93
93
  # In that case the output will be sent to STDOUT.
94
- $options["output_filename"] ||= 'lydown' unless $options["format"] == 'ly'
94
+ $options[:output_filename] ||= 'lydown' unless $options[:format] == 'ly'
95
95
  else
96
96
  filename = ARGV[0] || '.'
97
- $options['source_filename'] = filename
97
+ $options[:source_filename] = filename
98
98
  if (filename !~ /\.ld$/) and File.file?(filename + ".ld")
99
99
  filename += ".ld"
100
100
  end
101
101
 
102
- $options["output_filename"] ||= (filename =~ /^(.+)\.ld$/) ? $1 : filename
103
- end
104
-
105
- # compile score
106
- unless $options[:no_score] || $options[:parts]
107
- Lydown::CLI::Compiler.process($options.merge(mode: :score, parts: nil))
102
+ unless $options[:output_filename]
103
+ if filename == '.'
104
+ $options[:output_filename] = File.basename(FileUtils.pwd)
105
+ else
106
+ $options[:output_filename] = (filename =~ /^(.+)\.ld$/) ? $1 : filename
107
+ end
108
+ end
108
109
  end
109
110
 
110
- # compile parts
111
- unless $options[:score_only] || !$options[:parts]
112
- parts = $options[:parts]
113
- parts.each do |p|
114
- Lydown::CLI::Compiler.process($options.merge(mode: :part, parts: p))
111
+ if $options[:proof_mode]
112
+ Lydown::CLI::Proofing.start_proofing($options)
113
+ else
114
+ # compile score
115
+ unless $options[:no_score] || $options[:parts]
116
+ Lydown::CLI::Compiler.process($options.merge(mode: :score, parts: nil))
115
117
  end
116
- end
118
+
119
+ # compile parts
120
+ unless $options[:score_only] || !$options[:parts]
121
+ parts = $options[:parts]
122
+ parts.each do |p|
123
+ Lydown::CLI::Compiler.process($options.merge(mode: :part, parts: p))
124
+ end
125
+ end
126
+ end
@@ -68,6 +68,11 @@ module Lydown::CLI::Compiler
68
68
 
69
69
  if opts[:open_target]
70
70
  filename = "#{opts[:output_target]}.#{opts[:format]}"
71
+
72
+ unless File.file?(filename)
73
+ filename = "#{opts[:output_target]}-page1.#{opts[:format]}"
74
+ end
75
+
71
76
  system("open #{filename}")
72
77
  end
73
78
  end
@@ -0,0 +1,52 @@
1
+ require 'diff/lcs'
2
+
3
+ module Lydown::CLI::Diff
4
+ class << self
5
+ CACHE = {}
6
+
7
+ def cached_content(path)
8
+ CACHE[File.absolute_path(path)] || []
9
+ end
10
+
11
+ def set_cached_content(path, content)
12
+ CACHE[File.absolute_path(path)] = content
13
+ end
14
+
15
+ def fill_cache(dir)
16
+ count = 0
17
+ Dir["#{dir}/**/*.ld"].each do |path|
18
+ set_cached_content(path, read_content(path)) rescue nil
19
+ count += 1
20
+ end
21
+ puts "Cached #{count} files."
22
+ end
23
+
24
+ def read_content(path)
25
+ IO.read(path).lines.map {|l| l.chomp}
26
+ end
27
+
28
+ def diff_line_range(path)
29
+ new_version = read_content(path)
30
+ old_version = cached_content(path)
31
+
32
+ first = nil
33
+ last = nil
34
+
35
+ diffs = Diff::LCS.diff(old_version, new_version).each do |d|
36
+ d.each do |r|
37
+ line = r.to_a[1]
38
+ first = line if first.nil? || line < first
39
+ last = line if last.nil? || line > last
40
+ end
41
+ end
42
+
43
+ set_cached_content(path, new_version)
44
+
45
+ first..last
46
+ rescue => e
47
+ STDERR << e.message
48
+ STDERR << e.backtrace.join("\n")
49
+ nil..nil
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,97 @@
1
+ require 'directory_watcher'
2
+
3
+ module Lydown::CLI::Proofing
4
+ class << self
5
+ def start_proofing(opts)
6
+ source = opts[:source_filename]
7
+
8
+ Lydown::CLI::Diff.fill_cache(source)
9
+
10
+ puts "Proof mode: #{source} -> #{opts[:output_filename]}"
11
+ last_proof_path = nil
12
+
13
+ watch_directory(source, opts)
14
+ end
15
+
16
+ def watch_directory(source, opts)
17
+ dw = DirectoryWatcher.new(File.expand_path(source))
18
+ dw.interval = 0.25
19
+ dw.glob = ["#{source}/**/*.ld"]
20
+
21
+ dw.reset(true)
22
+ dw.add_observer do |*args|
23
+ t = Time.now.strftime("%Y-%m-%d %H:%M:%S")
24
+ args.each do |e|
25
+ if e.type = :modified
26
+ path = File.expand_path(e.path)
27
+ if path =~ /^#{File.expand_path(source)}\/(.+)/
28
+ path = $1
29
+ end
30
+ puts "[#{t}] Changed: #{path}"
31
+ 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
33
+ end
34
+ end
35
+ end
36
+
37
+ trap("INT") {return}
38
+ dw.start
39
+ loop {sleep 1000}
40
+ ensure
41
+ dw.stop
42
+ end
43
+
44
+ def globs(path)
45
+ Dir.chdir(path) do
46
+ 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
+ end
54
+
55
+ dirs = dirs.map { |x| "#{x}/**/*" }
56
+ dirs
57
+ end
58
+
59
+ def opts_for_path(path, opts)
60
+ path = path.gsub('/./', '/')
61
+ part = File.basename(path, '.*')
62
+ base = opts[:source_filename] || '.'
63
+ if base == '.'
64
+ base = File.expand_path(base)
65
+ end
66
+ dir = File.dirname(path)
67
+ if dir =~ /^\.\/(.+)$/
68
+ dir = $1
69
+ end
70
+ if dir =~ /#{base}\/([^\/]+)/
71
+ mvt = $1
72
+ else
73
+ mvt = nil
74
+ end
75
+
76
+ opts = {}.deep!
77
+ opts[:movements] = [mvt]
78
+ if opts[:score_only]
79
+ opts[:mode] = :score
80
+ else
81
+ opts[:parts] = [part]
82
+ opts[:mode] = part
83
+ opts[:line_range] = Lydown::CLI::Diff.diff_line_range(path)
84
+ end
85
+
86
+ opts
87
+ end
88
+
89
+ def process(opts)
90
+ if opts[:line_range] == (nil..nil)
91
+ puts "No change detected"
92
+ else
93
+ Lydown::CLI::Compiler.process(opts)
94
+ end
95
+ end
96
+ end
97
+ end
data/lib/lydown/cli.rb CHANGED
@@ -4,3 +4,5 @@ module Lydown
4
4
  end
5
5
 
6
6
  require 'lydown/cli/compiler'
7
+ require 'lydown/cli/proofing'
8
+ require 'lydown/cli/diff'
@@ -21,12 +21,30 @@ module Lydown
21
21
  tmp_target = Tempfile.new('lydown').path
22
22
  opts[:output_filename] = tmp_target
23
23
  invoke(source, opts)
24
- FileUtils.cp(tmp_target + ext, target)
24
+
25
+ if File.file?(tmp_target + ext)
26
+ FileUtils.cp(tmp_target + ext, target)
27
+ else
28
+ copy_pages(tmp_target, target, ext)
29
+ end
25
30
  rescue => e
26
31
  puts e.message
27
32
  p e.backtrace
28
33
  end
29
34
 
35
+ def copy_pages(source, target, ext)
36
+ page = 1
37
+ loop do
38
+ source_fn = source + "-page#{page}" + ext
39
+ break unless File.file?(source_fn)
40
+
41
+ target_fn = target.dup.insert(target.index(/\.[^\.]+$/), "-page#{page}")
42
+
43
+ FileUtils.cp(source_fn, target_fn)
44
+ page += 1
45
+ end
46
+ end
47
+
30
48
  def invoke(source, opts = {})
31
49
  # Run lilypond, pipe source into its STDIN, and capture its STDERR
32
50
  cmd = 'lilypond -lERROR '
@@ -46,4 +46,21 @@ ten = \markup { \italic ten. }
46
46
  ficta = {
47
47
  \once \override AccidentalSuggestion #'avoid-slur = #'outside
48
48
  \once \set suggestAccidentals = ##t
49
- }
49
+ }
50
+
51
+ %{
52
+ http://www.lilypond.org/doc/v2.18/Documentation/snippets/editorial-annotations#editorial-annotations-adding-links-to-objects
53
+ %}
54
+ #(define (add-link url-strg)
55
+ (lambda (grob)
56
+ (let* ((stil (ly:grob-property grob 'stencil)))
57
+ (if (ly:stencil? stil)
58
+ (begin
59
+ (let* (
60
+ (x-ext (ly:stencil-extent stil X))
61
+ (y-ext (ly:stencil-extent stil Y))
62
+ (url-expr (list 'url-link url-strg `(quote ,x-ext) `(quote ,y-ext)))
63
+ (new-stil (ly:stencil-add (ly:make-stencil url-expr x-ext y-ext) stil)))
64
+ (ly:grob-set-property! grob 'stencil new-stil)))
65
+ #f))))
66
+
@@ -29,14 +29,14 @@
29
29
 
30
30
  <<
31
31
 
32
- <% if part['settings'][:tempo] %>
33
- \tempo "<%= part['settings'][:tempo] %>"
34
- <% end %>
35
-
36
32
  \new Staff = <%= staff_id %> \with {
37
33
  }
38
34
 
39
35
  \context Staff = <%= staff_id %> {
36
+ <% if part['settings'][:tempo] %>
37
+ \tempo "<%= part['settings'][:tempo] %>"
38
+ <% end %>
39
+
40
40
  <% if score_mode %>\set Staff.instrumentName = #"<%= title %>"<% end %>
41
41
  \relative c {
42
42
  <% if clef %>
@@ -1,3 +1,3 @@
1
1
  module Lydown
2
- VERSION = "0.7.0"
2
+ VERSION = "0.7.1"
3
3
  end
data/lib/lydown/work.rb CHANGED
@@ -231,7 +231,7 @@ module Lydown
231
231
  preserve_context do
232
232
  process_lydown_file(entry, [
233
233
  {type: :setting, key: 'part', value: part}
234
- ])
234
+ ], line_range: @context[:options][:line_range])
235
235
  end
236
236
  end
237
237
  elsif File.directory?(entry) && recursive
@@ -245,9 +245,47 @@ module Lydown
245
245
  end
246
246
  end
247
247
  end
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
248
279
 
249
- def process_lydown_file(path, prefix = [])
250
- process(prefix + LydownParser.parse(IO.read(path))) if File.file?(path)
280
+ def process_lydown_file(path, prefix = [], opts = {})
281
+ return unless File.file?(path)
282
+
283
+ content = IO.read(path)
284
+ if opts[:line_range]
285
+ content = insert_skip_markers(content, opts[:line_range])
286
+ end
287
+
288
+ process(prefix + LydownParser.parse(content))
251
289
  end
252
290
  end
253
291
  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.0
4
+ version: 0.7.1
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-06-30 00:00:00.000000000 Z
11
+ date: 2015-07-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: treetop
@@ -37,6 +37,8 @@ files:
37
37
  - lib/lydown.rb
38
38
  - lib/lydown/cli.rb
39
39
  - lib/lydown/cli/compiler.rb
40
+ - lib/lydown/cli/diff.rb
41
+ - lib/lydown/cli/proofing.rb
40
42
  - lib/lydown/core_ext.rb
41
43
  - lib/lydown/errors.rb
42
44
  - lib/lydown/lilypond.rb