The code is now completely covered in specs
[lyrix.git] / lib / lyric_parser.rb
blob1747f782a249e19d3386103fd8088a47d288c8be
1 module Lyrix
2   class LyricParser
3     attr_reader :lyrics
4     
5     DEFAULT_OPTIONS = {} unless defined?(DEFAULT_OPTIONS)
6   
7     def initialize(lyrics, options = {})
8       @options = DEFAULT_OPTIONS.merge(options)
9       @lyrics = lyrics
10     end
11     
12     def lyrics=(lyrics)
13       @lyrics = lyrics
14       @parsed_lyrics = nil
15     end
16     
17     def parse
18       @parsed_lyrics ||= parse!
19       @parsed_lyrics
20     end
21     
22     def parse!
23       parsed = {}
24       
25       parsed[:slides] = @lyrics.strip.gsub("\r\n", "\n").split(/\n[ \t]*\n/)
26       parsed[:slides].collect! { |s| s.strip }
27       parsed[:slides].reject! { |s| s.empty? }
28       
29       parsed[:slides].each_with_index do |s,idx|
30         [:chorus, :bridge].each do |sub|
31           if s =~ Regexp.new("^\\[#{sub}\\]") and !parsed.has_key?(sub)
32             parsed[sub] = s.split("\n")[1..-1].join("\n")
33             parsed[:slides][idx] = parsed[sub]
34           end
35         
36           parsed[:slides][idx].gsub!("[#{sub}]", parsed[sub]) if parsed[sub]
37         end
38         
39         if s =~ /^\[([2-9])x\]/
40           parsed[:slides][idx] = (1..($1.to_i)).collect { s.split("\n")[1..-1].join("\n") }
41         end
42       end
43       
44       parsed[:slides].flatten!
45       
46       parsed[:slides].each_with_index do |s,idx|
47         slide = parsed[:slides][idx].split("\n")
48         slide.each_with_index do |line,i|
49           if line.strip =~ /\[([2-9])x\]$/
50             num = $1.to_i
51             line = line.gsub("[#{num}x]", "").strip
52             slide[i] = (1..num).collect { line }
53           end
54         end
55         parsed[:slides][idx] = slide.flatten.join("\n")
56       end
57       
58       parsed
59     end
60     
61     def to_slides
62       parse[:slides]
63     end
64   end
65 end