Skip to content

Instantly share code, notes, and snippets.

@kmckelvin
Created November 11, 2012 17:21
Show Gist options
  • Select an option

  • Save kmckelvin/4055586 to your computer and use it in GitHub Desktop.

Select an option

Save kmckelvin/4055586 to your computer and use it in GitHub Desktop.

Revisions

  1. kmckelvin revised this gist Nov 11, 2012. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -1,9 +1,9 @@
    ## Usage

    Pretty easy to use:
    Pretty easy to use - just make sure that Ruby is installed, then run this:

    ```
    opensong_to_onsong.rb ./path_to_opensong_file.xml > ./export_filename.txt
    ruby opensong_to_onsong.rb ./path_to_opensong_file.xml > ./export_filename.txt
    ```

    It just outputs straight to STDIO.
  2. kmckelvin revised this gist Nov 11, 2012. 1 changed file with 0 additions and 2 deletions.
    2 changes: 0 additions & 2 deletions opensong_to_onsong.rb
    Original file line number Diff line number Diff line change
    @@ -50,8 +50,6 @@ def to_lines(content)
    lines
    end

    p to_lines(content)

    def get_chord_positions(chord_line)
    positions = []

  3. kmckelvin revised this gist Nov 11, 2012. 1 changed file with 7 additions and 2 deletions.
    9 changes: 7 additions & 2 deletions opensong_to_onsong.rb
    Original file line number Diff line number Diff line change
    @@ -16,6 +16,7 @@ def to_lines(content)
    file_lines.each do |line|
    if pair.any?
    pair << line[1..-1]
    pair[1] ||= ""
    lines << pair
    pair = []
    elsif line[0] == '.' && pair.empty?
    @@ -49,6 +50,8 @@ def to_lines(content)
    lines
    end

    p to_lines(content)

    def get_chord_positions(chord_line)
    positions = []

    @@ -82,11 +85,14 @@ def interpolate_line(chord_positions, lyrics)

    chord_positions.each do |chord, position|
    insert_string = "[#{chord}]"
    if output.length < (position + offset)
    output << (" " * (position + offset - output.length))
    end
    output.insert(position + offset, insert_string)
    offset += insert_string.length
    end

    output
    output.strip
    end

    lines = to_lines(content)
    @@ -99,4 +105,3 @@ def interpolate_line(chord_positions, lyrics)
    onsong.each do |line|
    puts line
    end

  4. kmckelvin revised this gist Nov 11, 2012. 1 changed file with 2 additions and 0 deletions.
    2 changes: 2 additions & 0 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -2,7 +2,9 @@

    Pretty easy to use:

    ```
    opensong_to_onsong.rb ./path_to_opensong_file.xml > ./export_filename.txt
    ```

    It just outputs straight to STDIO.

  5. kmckelvin created this gist Nov 11, 2012.
    11 changes: 11 additions & 0 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,11 @@
    ## Usage

    Pretty easy to use:

    opensong_to_onsong.rb ./path_to_opensong_file.xml > ./export_filename.txt

    It just outputs straight to STDIO.

    ## Disclaimer

    I just put this together pretty quickly, and by no means intended to cover the entire OpenSong spec. In my trials it seems to work pretty accurately. If there are issues - drop me a message and I'll look into them :)
    102 changes: 102 additions & 0 deletions opensong_to_onsong.rb
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,102 @@
    require 'nokogiri'

    file = ARGV[0]

    xml = Nokogiri::XML(File.read(file))

    title = xml.css('title').text
    content = xml.css('lyrics').text

    def to_lines(content)
    file_lines = content.split("\n")
    lines = []

    pair = []

    file_lines.each do |line|
    if pair.any?
    pair << line[1..-1]
    lines << pair
    pair = []
    elsif line[0] == '.' && pair.empty?
    pair = [line[1..-1]]
    elsif line[0] == ' ' && pair.empty?
    pair = []
    lines << ["", line]
    elsif line =~ /\[V(\d*)\]/
    pair = []
    lines << ["", "Verse #{$1}:"]
    elsif line =~ /\[C(\d*)\]/
    pair = []
    number = $1.length != 0 ? " #{$1}" : ""
    lines << ["", "Chorus#{number}:"]
    elsif line =~ /\[PC(\d*)\]/
    pair = []
    number = $1.length != 0 ? " #{$1}" : ""
    lines << ["", "Prechorus#{number}:"]
    elsif line =~ /\[B(\d*)\]/
    pair = []
    number = $1.length != 0 ? " #{$1}" : ""
    lines << ["", "Bridge#{number}:"]
    elsif line.strip == ""
    pair = []
    lines << ["", ""]
    else
    pair = []
    end
    end

    lines
    end

    def get_chord_positions(chord_line)
    positions = []

    chord = ""
    start_pos = 0

    (0..chord_line.length - 1).each do |i|
    if chord_line[i] == ' ' && chord != ""
    positions << [chord, start_pos]
    chord = ""
    start_pos = 0
    end

    if chord_line[i] != ' '
    start_pos = i if chord == ""
    chord << chord_line[i]
    end
    end

    if chord != ""
    positions << [chord, start_pos]
    end

    positions
    end

    def interpolate_line(chord_positions, lyrics)
    output = lyrics.dup

    offset = 0

    chord_positions.each do |chord, position|
    insert_string = "[#{chord}]"
    output.insert(position + offset, insert_string)
    offset += insert_string.length
    end

    output
    end

    lines = to_lines(content)
    onsong = lines.map { |chords, lyrics| [get_chord_positions(chords), lyrics] }.map{ |chord_positions, lyrics| interpolate_line(chord_positions, lyrics) }

    key = get_chord_positions(lines.find { |chords, lyrics| chords.length != 0 }[0])[0][0] rescue nil

    puts title
    puts "Key: [#{key}]" if key
    onsong.each do |line|
    puts line
    end