From 63f98cf51be55ea324547815e1040ae1ab11e161 Mon Sep 17 00:00:00 2001 From: Alexandre Dupas Date: Mon, 7 Dec 2009 18:58:39 +0100 Subject: [PATCH] Add new version of the makeindex program. This new version is written in Python. It does not currently handle prefix directives but is set to ignore any special words defined into the songbook latex document. --- make-index | 127 ------------------------------------------ makefile | 2 +- songbook-makeindex.py | 124 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 125 insertions(+), 128 deletions(-) delete mode 100755 make-index create mode 100755 songbook-makeindex.py diff --git a/make-index b/make-index deleted file mode 100755 index 9bf405f7..00000000 --- a/make-index +++ /dev/null @@ -1,127 +0,0 @@ -#!/usr/bin/perl -w -# -# Generate indexes files for the Crep's chorbook compilation. This is a much -# simplified version from the original C programm that parse the input. -# -# Usage: mk-idx.pl SRC -# SRC should be an .sxd file generated by the latex songs package -# - -use warnings; -use strict; -use utf8; - -sub uppercase($) -{ - my $letter = shift; - $letter =~ tr/a-zàéèëê/A-ZAEEEE/; - return $letter; -} - -sub usage () -{ - die "usage: make-index [options] source", "\n"; -} - -my %options; - -sub getoptions () -{ - eval q{use Getopt::Long}; - Getopt::Long::Configure('pass_through'); - GetOptions( -# "verbose|v!" => \$options{verbose}, - ) || usage(); -} - -getoptions(); - -# Process command line -usage() unless @ARGV; -my $file = shift; - -# Open file and store data before closing the file -open( FILE, $file ) or die("unable to open $file"); -my @data = ; -close( FILE ); - -# Process data -my %table; - -# Get the type of the index. Not used but we have it. -my $type = shift @data; - -# Parse data and create the index table -my $item; -my $index; -my $link; -my $letter; -my $ref; - -my @prefix = (); - -while( @data && ( $data[0] =~ /^\s*%prefix (.*)$/ ) ) -{ - push @prefix, $1; - shift @data; -} - -# Create the prefix rule -my $prefix = '(('. join ("|", @prefix) . ')[\s])'; - -# Create the filter function -sub filter($) -{ - my $string = shift; - $string =~ /^$prefix?[^\w]*([\w])/; - - my $letter = uppercase $3; - $string =~ s/^$prefix\W*\w(.*)/$letter$3, $1/; - - $letter = "0-9" if ( $letter =~ /\d/ ); # group every numbers - - return (uppercase $letter, $string); -} - -# Process data -while( @data ) -{ - $item = shift @data; - # entry goes on three lines - chomp $item; - $index = shift @data; - chomp $index; - $link = shift @data; - chomp $link; - - # Get the first letter or number of the current item - ($letter, $item) = filter $item; - - # Create empty data index if needed - $table{$letter} = {} unless exists $table{$letter}; - $table{$letter}{$item} = [] unless exists $table{$letter}{$item}; - - # Create reference for the current item - $ref = { num => $index, link => $link }; - - # Add the reference to the index - push @{$table{$letter}{$item}}, $ref; -} - -# Create the index formated file -my @refs; - -foreach $letter ( sort keys %table ) -{ - print '\begin{idxblock}{'.$letter."}\n"; - foreach $item ( sort keys %{$table{$letter}} ) - { - print '\idxentry{'; - print $item; - print '}{'; - @refs = @{$table{$letter}{$item}}; - print join ("\\\\", map { "\\hyperlink{$_->{link}}{$_->{num}}" } @refs); - print '}'."\n"; - } - print '\end{idxblock}'."\n"; -} diff --git a/makefile b/makefile index 2836fa2d..4acf8f1f 100644 --- a/makefile +++ b/makefile @@ -27,7 +27,7 @@ PSF = $(CIBLE:%=%.ps.gz) SONGS = songs.sbd SONGS_SRC = $(shell ls songs/*/*.sg) -MAKE_INDEX=./make-index +MAKE_INDEX=./songbook-makeindex.py MAKE_SONGDB=./songbook-volume.py PRINT=printf "%s\n" PRINTTAB=printf "\t%s\n" diff --git a/songbook-makeindex.py b/songbook-makeindex.py new file mode 100755 index 00000000..ab001b1b --- /dev/null +++ b/songbook-makeindex.py @@ -0,0 +1,124 @@ +#!/usr/bin/python +# +# Generate indexes files for the Crep's chordbook compilation. This is +# a replacement for the original makeindex program written in C that +# produces an index file (.sbx) from a file generated by the latex +# compilation of the songbook (.sxd). +# +# Usage : songbook-makeindex.py src +# src is the .sxd file generated by latex +# + +import sys +import os.path +import glob +import re +from optparse import OptionParser + +# Pattern set to ignore latex command in title prefix +keywordPattern = re.compile(r"^%(\w+)\s?(\w*)") +firstLetterPattern = re.compile(r"^(?:\{?\\\w+\}?)*[^\w]*(\w)") + +class index: + data = dict() + keywords = dict() + + def filter(self, key): + letter = firstLetterPattern.match(key).group(1) + if re.match('\d',letter): + letter = '0-9' + return (letter, key) + + def keyword(self, key, word): + if not self.keywords.has_key(key): + self.keywords[key] = [] + self.keywords[key].append(word) + + def compileKeywords(self): + pass + + def add(self, key, number, link): + (first, key) = self.filter(key) + if not self.data.has_key(first): + self.data[first] = dict() + if not self.data[first].has_key(key): + self.data[first][key] = [] + self.data[first][key].append({'num':number, 'link':link}) + + def refToStr(self, ref): + if sys.version_info >= (2,6): + return '\\hyperlink{{{0[link]}}}{{{0[num]}}}'.format(ref) + else: + return '\\hyperlink{%(link)s}{%(num)s}' % ref + + def entryToStr(self, key, entry): + if sys.version_info >= (2,6): + return '\\idxentry{{{0}}}{{{1}}}\n'.format(key, '\\\\'.join(map(self.refToStr, entry))) + else: + return '\\idxentry{%s}{%s}\n' % (key, '\\\\'.join(map(self.refToStr, entry))) + + def idxBlockToStr(self, letter, entries): + str = '\\begin{idxblock}{'+letter+'}'+'\n' + for key in entries.keys(): + str += self.entryToStr(key, entries[key]) + str += '\\end{idxblock}'+'\n' + return str + + def entriesToStr(self): + str = "" + for letter in self.data.keys(): + str += self.idxBlockToStr(letter, self.data[letter]) + return str + +def processSXDEntry(tab): + return (tab[0], tab[1], tab[2]) + +def processSXD(filename): + file = open(filename) + data = [] + for line in file: + data.append(line.strip()) + file.close() + + type = data[0] + i = 1 + idx = index() + while data[i].startswith('%'): + keywords = keywordPattern.match(data[i]).groups() + idx.keyword(keywords[0],keywords[1]) + i += 1 + idx.compileKeywords() + for i in range(i,len(data),3): + entry = processSXDEntry(data[i:i+3]) + idx.add(entry[0],entry[1],entry[2]) + return idx + +def usage(exitCode=None): + print "usage: songbook-makeindex.py [options] source" + sys.exit(exitCode) + +def main(): + usage = "usage: %prog [options] FILE" + parser = OptionParser(usage) + parser.add_option("-o", "--output", dest="filename", + help="write result into FILE", metavar="FILE") + (options, args) = parser.parse_args() + + # Args processing + if len(args) != 1: + parser.error("incorrect number of arguments") + if not os.path.exists(args[0]): + parser.error("inexistant input file") + + # Options processing + if options.filename: + output = open(options.filename,"w") + else: + output = sys.stdout + + # Actual processing + idx = processSXD(args[0]) + output.write(idx.entriesToStr()) + +if __name__ == '__main__': + main()