class SongBook

Attributes

info[RW]
preface[RW]
songs[RW]

Public Class Methods

new() click to toggle source
# File Creator/song.rb, line 44
def initialize
  @songs = []
end
parse(dir) click to toggle source
# File Creator/parser.rb, line 147
def self.parse(dir)
  return SongBook.new.parse(dir)
end
templatize(str, options={}) click to toggle source
# File Creator/latex_formatter.rb, line 102
def self.templatize(str, options={})
  template = File.read(options[:template] || "#{File.dirname(__FILE__)}/../template.tex")
  if options[:booklet]
    template.gsub!('documentclass[letterpaper]{article}', 'documentclass[letterpaper]{book}')
    template.gsub!('usepackage[noprint,1to1]{booklet}', 'usepackage[print,1to1]{booklet}')
  end
  template.sub("SONGGOESHERE", str)
          .sub("PREFACEGOESHERE", options[:preface].to_s)
          .sub("TITLEGOESHERE", options.fetch(:title, "Untitled Songbook"))
          .sub("SUBTITLEGOESHERE", options.fetch(:subtitle, ""))
end

Public Instance Methods

build(options = {}) click to toggle source
# File Creator/latex_formatter.rb, line 91
def build(options = {})
  filename = options.fetch(:filename, "preview")
  File.write("#{filename}.tex", to_latex(options.merge(preface:self.preface)))
  2.times { raise StandardError.new("Could not build #{filename}") unless system("xelatex -shell-escape #{filename}.tex") }
end
file_safe_title() click to toggle source
# File Creator/song.rb, line 51
def file_safe_title; title.gsub(/[^\w]/,""); end
json_info() click to toggle source
# File Creator/html_formatter.rb, line 45
def json_info
  info = {}
  info['songs'] = songs.reject(&:hidden?).map(&:title)
  info['songInfo'] = songs.reject(&:hidden?).map do |song|
    Hash[%w[title slug key author desc emoji].map{|f| [f, song.__send__(f.to_sym)]}]
  end
  info['date'] = DateTime.now
  info['date_format'] = DateTime.now.strftime("%B %-d, %Y")

  return info.to_json
end
jsonp_info() click to toggle source
# File Creator/html_formatter.rb, line 57
def jsonp_info
  return %|window.songBookInfo = #{json_info};|
end
parse(dir) click to toggle source
# File Creator/parser.rb, line 107
def parse(dir)
  if File.exist?("#{dir}/../songbook.yml") then
    log.debug "Reading info file"
    @info = Hash[YAML.load(File.read("#{dir}/../songbook.yml")).map{|(k,v)| [k.to_sym,v]}]
  else
    raise StandardError.new("No such file #{dir}/songbook.yml")
  end

  Dir["#{dir}/*.chords"].each do |f|
    songs << Song.parse(f)
  end

  Dir["#{dir}/*.abc"].reject{|a| File.exist?("#{dir}/#{File.basename(a, ".abc")}.chords")}.each do |f|
    songs << Song.new.parse_abc(f)
  end

  # Allow include: syntax in songbook.yml to include songs from other songbooks
  @info.fetch(:include, {}).each do |inc_dir, song_list|
    Dir["#{inc_dir}/*.chords"].each do |f|
      new_song = Song.parse(f)
      songs << new_song if song_list.nil? or song_list.empty? or song_list.include?(new_song.slug)
    end
    Dir["#{inc_dir}/*.abc"].reject{|a| File.exist?("#{inc_dir}/#{File.basename(a, ".abc")}.chords")}.each do |f|
      new_song = Song.new.parse_abc(f)
      songs << new_song if song_list.nil? or song_list.empty? or song_list.include?(new_song.slug)
    end
  end

  if File.exist?("#{dir}/order.yml") then
    # Looks better in the yml file as ##: slug
    order = Hash[YAML.load(File.read("#{dir}/order.yml")).map{|k,v| [v, k]}] || {}
    max = order.values.max || 0
    songs.each{|s| s.order = order.fetch(s.slug, max += 1) || max += 1}
    songs.sort_by!(&:order)
    songs.each_with_index{|s, i| s.order = i + 1}
  end

  return self
end
preview(options = {}) click to toggle source
# File Creator/latex_formatter.rb, line 97
def preview(options = {})
  build(options)
  spawn("evince #{filename}.pdf")
end
subtitle() click to toggle source
# File Creator/song.rb, line 49
def subtitle; info[:subtitle]; end
title() click to toggle source
# File Creator/song.rb, line 48
def title; info[:title]; end
to_html(dir, opts = {}) click to toggle source
# File Creator/html_formatter.rb, line 61
def to_html(dir, opts = {})
  scope = OpenStruct.new(book: self)
  log.info "Creating songbook in #{dir}"
  File.write("#{dir}/songbook.html", Slim::Template.new(File.join(File.dirname(__FILE__),'songbook.slim')).render(scope))
  File.write("#{dir}/tv.html", Slim::Template.new(File.join(File.dirname(__FILE__),'tv.slim')).render(scope))
  log.debug "Options: #{opts}"
  songs.each do |song|
    next if opts.has_key?(:only) and not opts[:only].include?(song.slug)
    log.debug("Creating song page for #{song.title}")
    scope = OpenStruct.new(song: song)
    File.write("#{dir}/#{song.slug}.html", Slim::Template.new(File.join(File.dirname(__FILE__),'song.slim')).render(scope))
    File.write("#{dir}/#{song.slug}_slideable.html", Slim::Template.new(File.join(File.dirname(__FILE__),'slideable_song.slim')).render(scope))
  end
  Dir["#{File.dirname(__FILE__)}/*.coffee"].each do |c|
    log.debug "Compiling #{c}"
    File.write("#{dir}/#{File.basename(c, ".coffee")}.js", CoffeeScript.compile(File.read(c)))
  end
  FileUtils.cp Dir["#{File.dirname(__FILE__)}/resources/*"], "#{dir}/"
end
to_latex(options = {}) click to toggle source
# File Creator/latex_formatter.rb, line 84
def to_latex(options = {})
  SongBook.templatize(songs.reject{|s| s.hidden?}.sort_by do |s|
    #[s.song? ? 0 : 1, s.short? ? 1 :0, File.ctime(s.file)]
    s.order
  end.collect{|s| s.to_latex}.join("\n"), options.merge(@info))
end
to_midi(dir) click to toggle source
# File Creator/midi_formatter.rb, line 19
def to_midi(dir)
  FileUtils.mkdir_p dir
  Dir.chdir(dir) do
    songs.each(&:to_midi)
  end
end