#!/usr/bin/ruby

USAGE = "Usage: footnotes.rb [options] <file>
   -t, --target     Sort footnotes by their position in target section instead
                    of appearance in text.
   -T, --test       Do a self test, using text appended to the script.
   -h, --help       Show this message.
"

# Given an input and (optionally) output stream, this method does the actual
# footnote sorting.
def sort_footnotes(input, output=STDOUT)
       # initialize translation table
       footnote_counter = 0
       old2new = Hash.new { |hash, key| hash[key] = (footnote_counter += 1) }

       # If we are to sort by the position in the target section, we need to scan
       # that section first, then rewind the stream and start processing.
       if $sort_by_target
               until input.readline =~ /^@footnote:/ do end
               input.each_line do |line|
                       if line =~ /^\[(\d+)\]/ then old2new[$1] end
               end
               input.rewind
       end
       targets = [] # note: targets[0] remains empty (nil)
       input.each_line do |line|
               unless (line =~ /^@footnote:/) .. false
                       output.puts line.gsub(/\[(\d+)\]/) { "[" + old2new[$1].to_s + "]" }
               else
                       # we are within the target section
                       if line =~ /^\[(\d+)\](.*)/
                               targets[old2new[$1]] = $2
                       else
                               output.puts line
                       end
               end
       end
       (1...targets.size).each { |nr| output.puts "[#{nr}]#{targets[nr]}" }
end

# handle command-line options, calling sort_footnotes to do the actual work
if ARGV.delete("--help") || ARGV.delete("-h")
       puts USAGE; exit
end
$sort_by_target = ARGV.delete("--target") || ARGV.delete("-t")
if ARGV.delete("--test") || ARGV.delete("-T")
       sort_footnotes StringIO.new(DATA.read)
elsif ARGV[0]
       File.open(ARGV[0], "r") { |file| sort_footnotes file }
else
       puts USAGE
end

__END__
A great brown fox [13] jumped off a pile
of lorem ipsum [4], [7]. He met with a
silver penguin [13], browsing the Linux Kernel
Mailinglist [3]. They debated over the
question whether to start a C-program with
"main (int argc, char **argv)" or with
"main (int argc, char *argv[])". Square
brackets annoyed them [9999].
@footnote:
[13] Al Fabetus: "On characters and animals", 1888, self published
[4] Lorem Ipsum, <a href="http://en.wikipedia.org/wiki/Lorem_ipsum">Web Link</a>
[9999] Annoying Link.
[7] B. Fox: "More on Blind Text"
[3] Linux Kernel Maintainers: LKML