lydown 0.7.0 → 0.7.1

Sign up to get free protection for your applications and to get access to all the features.
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