#!/usr/bin/python # -*- coding: utf-8 -*- # 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 os.path import glob import re import sys from optparse import OptionParser import sortindex import locale # Pattern set to ignore latex command in title prefix keywordPattern = re.compile(r"^%(\w+)\s?(.*)$") 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.upper(), key) def keyword(self, key, word): if not self.keywords.has_key(key): self.keywords[key] = [] self.keywords[key].append(word) def compileKeywords(self): self.prefix_patterns = [] if 'prefix' in self.keywords: for prefix in self.keywords['prefix']: self.prefix_patterns.append(re.compile(r"^(%s)\b\s*(.*)$" % prefix)) def add(self, key, number, link): for pattern in self.prefix_patterns: match = pattern.match(key) if match: key = "%s (%s)" % (match.group(2), match.group(1)) break # Only one match per key (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 sorted(entries.keys(), key=sortindex.sortkey): str += self.entryToStr(key, entries[key]) str += '\\end{idxblock}'+'\n' return str def entriesToStr(self): str = "" for letter in sorted(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() if len(data) > 1: 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(): locale.setlocale(locale.LC_ALL, '') 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()