lydown 0.10.0 → 0.12.4

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.
data/bin/lydown CHANGED
@@ -2,4 +2,8 @@
2
2
 
3
3
  require 'lydown/cli'
4
4
 
5
- Lydown::CLI::Commands.start(ARGV)
5
+ if ARGV.empty?
6
+ Lydown::CLI::REPL.run
7
+ else
8
+ Lydown::CLI::Commands.start(ARGV)
9
+ end
@@ -1,5 +1,4 @@
1
1
  require 'digest/md5'
2
- require 'msgpack'
3
2
 
4
3
  module Cache
5
4
  class << self
@@ -26,7 +25,7 @@ module Cache
26
25
 
27
26
  def calculate_hash(*params)
28
27
  params.map do |p|
29
- Digest::MD5.hexdigest(p.is_a?(String) ? p : p.to_msgpack)
28
+ Digest::MD5.hexdigest(p.is_a?(String) ? p : p.to_s)
30
29
  end.join('-')
31
30
  end
32
31
 
@@ -9,5 +9,7 @@ require 'lydown/cli/proofing'
9
9
  require 'lydown/cli/diff'
10
10
  require 'lydown/cli/translation'
11
11
  require 'lydown/cli/output'
12
+ require 'lydown/cli/repl'
13
+ require 'lydown/cli/installer'
12
14
  require 'lydown/cli/commands'
13
15
  require 'lydown/cli/signals'
@@ -5,15 +5,19 @@ module Lydown::CLI
5
5
  desc "version", "show Lydown version"
6
6
  def version
7
7
  require 'lydown/version'
8
+ $stderr.puts "Lydown version #{Lydown::VERSION}"
8
9
 
9
- puts "Lydown version #{Lydown::VERSION}"
10
- exit!(0)
10
+ lilypond_version = Lydown::CLI::Support.detect_lilypond_version(false)
11
+ if lilypond_version
12
+ $stderr.puts "Lilypond version #{lilypond_version}"
13
+ end
11
14
  end
12
-
15
+
13
16
  desc "compile [PATH]", "compile the lydown source at PATH"
14
17
  method_option :format, aliases: '-f',
15
18
  default: 'pdf', desc: 'Set output format (pdf/png/ly/midi/mp3)',
16
19
  enum: %w{pdf png ly midi mp3}
20
+ method_option :pdf, type: :boolean, desc: 'Set PDF output format'
17
21
  method_option :png, type: :boolean, desc: 'Set PNG output format'
18
22
  method_option :ly, type: :boolean, desc: 'Set Lilypond output format'
19
23
  method_option :midi, type: :boolean, desc: 'Set MIDI output format'
@@ -35,14 +39,23 @@ module Lydown::CLI
35
39
  desc: 'Create separate file for each movement'
36
40
  method_option :verbose, type: :boolean
37
41
  def compile(*args)
42
+ path = args.first || '.'
43
+
44
+ # check if user specified a command as an argument (e.g. --version)
45
+ if (path =~ /^\-\-(\w+)/) && respond_to?($1)
46
+ return send($1)
47
+ end
48
+
49
+ Lydown::CLI::Support.detect_lilypond_version(true)
50
+
38
51
  require 'lydown'
39
52
 
40
53
  opts = Lydown::CLI::Support.copy_options(options)
41
- opts[:path] = args.first || '.'
54
+ opts[:path] = path
42
55
 
43
56
  # Set format based on direct flag
44
57
  opts[:format] = opts[:format].to_sym if opts[:format]
45
- [:png, :ly, :midi, :mp3].each {|f| opts[:format] = f if opts[f]}
58
+ [:pdf, :png, :ly, :midi, :mp3].each {|f| opts[:format] = f if opts[f]}
46
59
 
47
60
  opts[:parts] = opts[:parts].split(',') if opts[:parts]
48
61
  opts[:movements] = opts[:movements].split(',') if opts[:movements]
@@ -51,8 +64,6 @@ module Lydown::CLI
51
64
  Lydown::CLI::Support.detect_work_directory(opts)
52
65
  Lydown::CLI::Support.detect_filename(opts)
53
66
 
54
- p opts
55
-
56
67
  if (opts[:format] == :midi) || (opts[:format] == :mp3)
57
68
  opts[:score_only] = true
58
69
  opts[:parts_only] = false
@@ -77,6 +88,8 @@ module Lydown::CLI
77
88
  enum: %w{pdf png ly}
78
89
  method_option :include_parts, aliases: '-i', desc: 'Include parts (comma separated)'
79
90
  def proof(*args)
91
+ Lydown::CLI::Support.detect_lilypond_version(true)
92
+
80
93
  require 'lydown'
81
94
 
82
95
  opts = Lydown::CLI::Support.copy_options(options)
@@ -102,6 +115,11 @@ module Lydown::CLI
102
115
  Lydown::CLI::Translation.process(opts)
103
116
  end
104
117
 
118
+ desc "install [PACKAGE] [VERSION]", "install a package"
119
+ def install(*args)
120
+ Lydown::CLI::Installer.install(*args)
121
+ end
122
+
105
123
  def method_missing(method, *args)
106
124
  args = ["compile", method.to_s] + args
107
125
  self.class.start(args)
@@ -18,16 +18,26 @@ module Lydown::CLI::Compiler
18
18
  }
19
19
 
20
20
  def process(opts)
21
- t1 = Time.now
21
+ @start_time = Time.now
22
22
 
23
23
  opts = opts.deep_clone
24
24
  work = create_work_from_opts(opts)
25
25
 
26
26
  jobs = create_jobs_from_opts(work, opts)
27
+
28
+ # check if no jobs were created. This could happen when lydown processes
29
+ # parts but no parts are found
30
+ if jobs[:compile].empty?
31
+ $stderr.puts "No parts found."
32
+ return
33
+ end
34
+
27
35
  process_jobs(work, jobs, opts)
28
36
 
29
- t2 = Time.now
30
- $stderr.puts "Elapsed: #{'%.1f' % [t2-t1]}s"
37
+ now = Time.now
38
+ unless opts[:silent] || opts[:format] == :midi
39
+ $stderr.puts "Elapsed: #{'%.1f' % [now - @start_time]}s"
40
+ end
31
41
  end
32
42
 
33
43
  def create_jobs_from_opts(work, opts)
@@ -212,7 +222,7 @@ module Lydown::CLI::Compiler
212
222
  end
213
223
 
214
224
  def open_target(opts)
215
- filename = "#{opts[:output_target]}.#{opts[:format]}"
225
+ filename = "#{opts[:output_target]}.#{opts[:format] || 'pdf'}"
216
226
 
217
227
  unless File.file?(filename)
218
228
  filename2 = "#{opts[:output_target]}-page1.#{opts[:format]}"
@@ -224,18 +234,31 @@ module Lydown::CLI::Compiler
224
234
  end
225
235
 
226
236
  if opts[:format] == :midi
227
- open_midi_target(filename)
237
+ open_midi_target(filename, opts)
228
238
  else
229
239
  system("open #{filename}")
230
240
  end
231
241
  end
232
242
 
233
- def open_midi_target(filename)
243
+ def open_midi_target(filename, opts)
244
+ now = Time.now
245
+ unless opts[:silent]
246
+ $stderr.puts "Elapsed: #{'%.1f' % [now - @start_time]}s"
247
+ end
248
+
234
249
  $stderr << "Playing #{filename}..."
235
250
  Open3.popen2e("timidity #{filename}") do |input, output, wait_thr|
236
- input.close
237
- output.read
238
- output.close
251
+ begin
252
+ prev_handler = trap("INT") do
253
+ Process.kill("INT", wait_thr.pid)
254
+ prev_handler.call if prev_handler
255
+ end
256
+ input.close
257
+ output.read
258
+ output.close
259
+ ensure
260
+ trap("INT", prev_handler)
261
+ end
239
262
  end
240
263
  end
241
264
  end
@@ -18,7 +18,7 @@ module Lydown::CLI::Diff
18
18
  set_cached_content(path, read_content(path)) rescue nil
19
19
  count += 1
20
20
  end
21
- $stderr.puts "Cached #{count} files."
21
+ # $stderr.puts "Cached #{count} files."
22
22
  end
23
23
 
24
24
  def read_content(path)
@@ -0,0 +1,175 @@
1
+ require 'net/http'
2
+ require 'uri'
3
+ require 'ruby-progressbar'
4
+ require 'tempfile'
5
+ require 'fileutils'
6
+
7
+ module Lydown::CLI::Installer
8
+ class << self
9
+ def install(package, version = nil)
10
+ case package
11
+ when 'lilypond'
12
+ Lilypond.install(version)
13
+ else
14
+ STDERR.puts "Unknown package name specified"
15
+ exit!(1)
16
+ end
17
+ end
18
+ end
19
+
20
+ module Lilypond
21
+ class << self
22
+ LILYPOND_DEFAULT_VERSION = "2.19.29"
23
+
24
+ def detect_version(specified_version)
25
+ case specified_version
26
+ when nil, 'stable'
27
+ list = get_version_list
28
+ end
29
+ end
30
+
31
+ def install(version = nil)
32
+ platform = detect_lilypond_platform
33
+ version ||= LILYPOND_DEFAULT_VERSION
34
+ # version = detect_version(version)
35
+ url = lilypond_install_url(platform, version)
36
+ fn = Tempfile.new('lydown-lilypond-installer').path
37
+
38
+ download_lilypond(url, fn)
39
+ install_lilypond_files(fn, platform, version)
40
+ rescue => e
41
+ STDERR.puts "Failed to install lilypond #{version}"
42
+ puts e.message
43
+ puts e.backtrace.join("\n")
44
+ exit(1)
45
+ end
46
+
47
+ BASE_URL = "http://download.linuxaudio.org/lilypond/binaries"
48
+
49
+ def lilypond_install_url(platform, version)
50
+ ext = platform =~ /darwin/ ? ".tar.bz2" : ".sh"
51
+ filename = "lilypond-#{version}-1.#{platform}"
52
+
53
+ "#{BASE_URL}/#{platform}/#{filename}#{ext}"
54
+ end
55
+
56
+ def detect_lilypond_platform
57
+ case RUBY_PLATFORM
58
+ when /x86_64-darwin/
59
+ "darwin-x86"
60
+ when /ppc-darwin/
61
+ "darwin-ppc"
62
+ when "i686-linux"
63
+ "linux-x86"
64
+ when "x86_64-linux"
65
+ "linux-64"
66
+ when "ppc-linux"
67
+ "linux-ppc"
68
+ end
69
+ end
70
+
71
+ def download_lilypond(url, fn)
72
+ STDERR.puts "Downloading #{url}"
73
+
74
+ url_base = url.split('/')[2]
75
+ url_path = '/'+url.split('/')[3..-1].join('/')
76
+ download_count = 0
77
+
78
+ Net::HTTP.start(url_base) do |http|
79
+ request_url = URI.escape(url_path)
80
+ response = http.request_head(request_url)
81
+ total_size = response['content-length'].to_i
82
+ pbar = ProgressBar.create(title: 'Downloading', total: total_size)
83
+ File.open(fn, 'w') do |f|
84
+ http.get(request_url) do |data|
85
+ f << data
86
+ download_count += data.length
87
+ pbar.progress = download_count if download_count <= total_size
88
+ end
89
+ end
90
+ pbar.finish
91
+ end
92
+ end
93
+
94
+ def install_lilypond_files(fn, platform, version)
95
+ case platform
96
+ when /darwin/
97
+ install_lilypond_files_osx(fn, version)
98
+ when /linux/
99
+ install_lilypond_files_linux(fn, version)
100
+ end
101
+ end
102
+
103
+ def install_lilypond_files_osx(fn, version)
104
+ target = "/tmp/lydown/installer/lilypond"
105
+ FileUtils.mkdir_p(target)
106
+
107
+ STDERR.puts "Extracting..."
108
+ exec "tar -xjf #{fn} -C #{target}"
109
+
110
+ copy_lilypond_files("#{target}/LilyPond.app/Contents/Resources", version)
111
+ end
112
+
113
+ def install_lilypond_files_linux(fn, version)
114
+ target = "/tmp/lydown/installer/lilypond"
115
+ FileUtils.mkdir_p(target)
116
+
117
+ # create temp directory in which to untar file
118
+ tmp_dir = "/tmp/lydown/#{Time.now.to_f}"
119
+ FileUtils.mkdir_p(tmp_dir)
120
+
121
+ FileUtils.cd(tmp_dir) do
122
+ exec "sh #{fn} --tarball"
123
+ end
124
+
125
+ STDERR.puts "Extracting..."
126
+ exec "tar -xjf #{tmp_dir}/#{fn} -C #{target}"
127
+
128
+ copy_lilypond_files_linux("#{target}/usr", version)
129
+ end
130
+
131
+ def copy_lilypond_files(base_path, version)
132
+ target_dir = File.expand_path("~/.lydown/packages/lilypond/#{version}")
133
+
134
+ FileUtils.rm_rf(target_dir) if File.exists?(target_dir)
135
+
136
+ # create directory for lilypond files
137
+ FileUtils.mkdir_p(target_dir)
138
+
139
+ # copy files
140
+ STDERR.puts "Copying..."
141
+ %w{bin etc lib lib64 share var}.each do |entry|
142
+ dir = File.join(base_path, entry)
143
+ FileUtils.cp_r(dir, target_dir, remove_destination: true) if File.directory?(dir)
144
+ end
145
+
146
+ install_lilypond_executable(base_path, version)
147
+ end
148
+
149
+ BIN_SCRIPT_PATH = "#{File.expand_path('~')}/bin/lilypond"
150
+
151
+ def install_lilypond_executable(base_path, version)
152
+ target_dir = File.expand_path("~/.lydown/packages/lilypond/#{version}")
153
+
154
+ script = "#!/bin/sh\n#{target_dir}/bin/lilypond \"$@\"\n"
155
+
156
+ # create executable
157
+ FileUtils.rm(BIN_SCRIPT_PATH) if File.file?(BIN_SCRIPT_PATH)
158
+ File.open(BIN_SCRIPT_PATH, 'w+') {|f| f << script}
159
+ FileUtils.chmod('+x', BIN_SCRIPT_PATH)
160
+ # symlink_path = File.expand_path('~/bin/lilypond')
161
+ # FileUtils.ln_sf("#{target_dir}/bin/lilypond", symlink_path)
162
+
163
+ test_lilypond
164
+ end
165
+
166
+ def test_lilypond
167
+ STDERR.puts `lilypond -v`
168
+ end
169
+
170
+ def exec(cmd)
171
+ raise unless system(cmd)
172
+ end
173
+ end
174
+ end
175
+ end
@@ -3,55 +3,55 @@ require 'directory_watcher'
3
3
  module Lydown::CLI::Proofing
4
4
  class << self
5
5
  def start_proofing(opts)
6
- source = opts[:source_filename]
7
-
8
- Lydown::CLI::Diff.fill_cache(source)
9
-
10
6
  $stderr.puts "Proof mode: #{source} -> #{opts[:output_filename]}"
11
- last_proof_path = nil
12
7
 
13
- watch_directory(source, opts)
14
- end
15
-
16
- def watch_directory(source, opts)
17
- dw = DirectoryWatcher.new(
18
- File.expand_path(source),
19
- glob: ["**/*.ld"],
20
- pre_load: true
21
- )
22
- dw.interval = 0.25
23
-
24
- dw.add_observer do |*args|
25
- args.each do |e|
26
- if e.type == :modified
27
- path = File.expand_path(e.path)
28
- if path =~ /^#{File.expand_path(source)}\/(.+)/
29
- path = $1
30
- end
31
- last_proof_path = e.path unless File.basename(e.path) == 'movement.ld'
32
- if last_proof_path
33
- file_opts = opts.deep_merge opts_for_path(last_proof_path, opts)
34
- file_opts[:base_path] = path
35
- process(file_opts)
36
- end
37
- end
38
- end
39
- end
40
-
41
8
  trap("INT") {return}
42
- dw.start
9
+ watch(opts)
43
10
  loop {sleep 1000}
44
11
  ensure
45
- dw.stop
12
+ unwatch
46
13
  end
47
14
 
48
- def globs(path)
49
- Dir.chdir(path) do
50
- dirs = Dir['*'].select { |x| File.directory?(x) }
15
+ def watch(opts)
16
+ unwatch # teardown previous watcher
17
+
18
+ source = opts[:source_filename]
19
+ Lydown::CLI::Diff.fill_cache(source)
20
+ @last_proof_path = nil
21
+
22
+ @watcher = DirectoryWatcher.new(source, glob: ["**/*.ld"], pre_load: true)
23
+
24
+ @watcher.interval = 0.25
25
+ @watcher.add_observer do |*events|
26
+ events.each do |e|
27
+ handle_changed_file(e, opts) if e.type == :modified
28
+ end
51
29
  end
30
+ @watcher.start
31
+ end
52
32
 
53
- dirs = dirs.map { |x| "#{x}/**/*" }
54
- dirs
33
+ def unwatch
34
+ return unless @watcher
35
+
36
+ @watcher.stop
37
+ @watcher = nil
38
+ end
39
+
40
+ def handle_changed_file(event, opts)
41
+ path = File.expand_path(event.path)
42
+ if path =~ /^#{opts[:source_filename]}\/(.+)/
43
+ path = $1
44
+ end
45
+ @last_proof_path = event.path unless File.basename(event.path) == 'movement.ld'
46
+ if @last_proof_path
47
+ file_opts = opts.deep_merge(opts_for_path(@last_proof_path, opts))
48
+ file_opts[:base_path] = path
49
+ process(file_opts)
50
+ end
51
+ rescue => e
52
+ puts e.class
53
+ puts e.message
54
+ puts e.backtrace.join("\n")
55
55
  end
56
56
 
57
57
  def opts_for_path(path, opts)
@@ -87,7 +87,10 @@ module Lydown::CLI::Proofing
87
87
  def process(opts)
88
88
  if opts[:line_range] != [nil, nil]
89
89
  t = Time.now.strftime("%H:%M:%S")
90
- $stderr.puts "[#{t}] Changed: #{opts[:base_path]} (lines #{opts[:line_range][0]}..#{opts[:line_range][1]})"
90
+ unless opts[:silent]
91
+ $stderr.puts "[#{t}] Changed: #{opts[:base_path]} \
92
+ (lines #{opts[:line_range][0]}..#{opts[:line_range][1]})"
93
+ end
91
94
  Lydown::CLI::Compiler.process(opts)
92
95
  end
93
96
  end