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 +4 -4
- data/bin/lydown +42 -32
- data/lib/lydown/cli/compiler.rb +5 -0
- data/lib/lydown/cli/diff.rb +52 -0
- data/lib/lydown/cli/proofing.rb +97 -0
- data/lib/lydown/cli.rb +2 -0
- data/lib/lydown/lilypond.rb +19 -1
- data/lib/lydown/rendering/lib.ly +18 -1
- data/lib/lydown/templates/part.erb +4 -4
- data/lib/lydown/version.rb +1 -1
- data/lib/lydown/work.rb +41 -3
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8f9e00d9938576429da9646dc782f2451c66afa9
|
4
|
+
data.tar.gz: 3fe22010c7e1928c74a5278eb659dc78922a53a8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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[
|
26
|
+
$options[:parts] = v.split(',')
|
27
27
|
end
|
28
28
|
|
29
29
|
opts.on("-m", "--mvts MVT", "Movements (comma-separated)") do |v|
|
30
|
-
$options[
|
30
|
+
$options[:movements] = v.split(',')
|
31
31
|
end
|
32
32
|
|
33
33
|
opts.on("--no-score", "Do not generate secore") do
|
34
|
-
$options[
|
34
|
+
$options[:no_score] = true
|
35
35
|
end
|
36
36
|
|
37
37
|
opts.on("-s", "--score", "Generate only score, no parts") do
|
38
|
-
$options[
|
38
|
+
$options[:score_only] = true
|
39
39
|
end
|
40
40
|
|
41
41
|
opts.on("-V", "--vocal", "Generate only vocal score") do
|
42
|
-
$options[
|
42
|
+
$options[:vocal_only] = true
|
43
43
|
end
|
44
44
|
|
45
45
|
opts.on("--ly", "Generate Lilypond file") do
|
46
|
-
$options[
|
46
|
+
$options[:format] = 'ly'
|
47
47
|
end
|
48
48
|
|
49
49
|
opts.on("--pdf", "Generate PDF file") do
|
50
|
-
$options[
|
50
|
+
$options[:format] = 'pdf'
|
51
51
|
end
|
52
52
|
|
53
53
|
opts.on("--png", "Generate PNG file") do
|
54
|
-
$options[
|
54
|
+
$options[:format] = 'png'
|
55
55
|
end
|
56
56
|
|
57
57
|
opts.on("-M", "--midi", "Generate midi file") do
|
58
|
-
$options[
|
59
|
-
$options[
|
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[
|
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[
|
68
|
+
$options[:open_target] = true
|
68
69
|
end
|
69
70
|
|
70
71
|
opts.on("-o", "--output FILE", "Filename for output") do |v|
|
71
|
-
$options[
|
72
|
+
$options[:output_filename] = v
|
72
73
|
end
|
73
74
|
|
74
75
|
opts.on("-W", "--work", "Create new work") do
|
75
|
-
$options[
|
76
|
+
$options[:gen] = :work
|
76
77
|
end
|
77
78
|
end
|
78
79
|
|
79
80
|
opts.parse!
|
80
|
-
$options.deep!
|
81
81
|
|
82
|
-
if $options[
|
83
|
-
# Ripple.generate($options[
|
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[
|
94
|
+
$options[:output_filename] ||= 'lydown' unless $options[:format] == 'ly'
|
95
95
|
else
|
96
96
|
filename = ARGV[0] || '.'
|
97
|
-
$options[
|
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[
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
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
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
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
|
-
|
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
|
data/lib/lydown/cli/compiler.rb
CHANGED
@@ -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
data/lib/lydown/lilypond.rb
CHANGED
@@ -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
|
-
|
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 '
|
data/lib/lydown/rendering/lib.ly
CHANGED
@@ -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 %>
|
data/lib/lydown/version.rb
CHANGED
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
|
-
|
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.
|
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-
|
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
|