]> git.donarmstrong.com Git - lilypond.git/blob - scripts/mudela-book.py
release: 1.1.23
[lilypond.git] / scripts / mudela-book.py
1 #!@PYTHON@
2 #
3 # The bugs you find are made by Tom Cato Amundsen <tomcato@xoommail.com>
4 # Send patches/questions/bugreports to a mailinglist:
5 #  gnu-music-discuss@gnu.org
6 #  bug-gnu-music@gnu.org
7 #  help-gnu-music@gnu.org
8 #
9 # All non-english comments are NOT in swedish, they are norwegian!
10 #  TODO:
11 # * center option (??)
12 # * make mudela-book understand usepackage{geometry}
13 # * check that linewidth set in \paper is not wider than actual linewidth?
14 # * the following fails because mudelabook doesn't care that the
15 #   last } after \end{mudela} finishes the marginpar:
16 #     \marginpar{
17 #     \begin{mudela}
18 #        c d e f g
19 #     \end{mudela}}
20 # * force-verbatim is maybe not that useful since latex fails with footnotes,
21 #   marginpars and others
22 # log:
23 # 0.3:
24 #   rewrite in Python.
25 # 0.4:
26 #   much rewritten by new author. I think the work has been split more
27 #   logical between different classes.
28 # 0.4.1:
29 #   - cleanup
30 #   - speedup, do all mudela parsing at the same time to avoid multiple
31 #     guile startup that takes some seconds on my computer
32 # 0.4.2:
33 #   - fixed default latex fontsize, it should be 10pt not 11pt
34 #   - verbatim option no longer visible
35 #   - mudela-book produces .dvi output
36 #   - change to use castingalgorithm = \Gourlay instead of \Wordwrap. It gives
37 #     better result on small linewidths.
38 #   - mudela-book-doc.doc rewritten
39 # 0.5:
40 #   - junked floating and fragment options, added eps option
41 #   - mudela-book will scan the mudela code to find out if it has to add
42 #     paper-definition and \score{\notes{...}}
43 #   - possible to define commands that look like this: \mudela{ c d e }
44 #   - don't produce .dvi output, it was a silly idea...
45 # 0.5.1:
46 #   - removed init/mudela-book-defs.py, \mudela is defined inside mudela-book
47 #   - fragment and nonfragment options will override autodetection of type of
48 #     in mudela-block (voice contents or complete code)
49 # 0.5.2:
50 #   - fixed verbatim option behaviour: don't show \begin{mudela} \end{mudela}
51 #     and show both mudela code and music
52 #   - veryverbatim option, same as verbatim but show \begin{mudela}
53 #     and \end{mudela}. (saves keystrokes in mudela-book-doc.doc)
54 #   - intertext="bla bla bla" option
55 #   - mudela-book now understand latex \begin{verbatim}
56 # 0.5.3:
57 #   - bf: \mudela{ \times 2/3{...} }
58 #        * \t in \times is not tab character and
59 #        * dont treat the first '}' as command ending
60
61 import os
62 import string
63 import re
64 import getopt
65 import sys
66
67 outdir = 'out'
68 initfile = ''
69 program_version = '0.5.3'
70
71 out_files = []
72
73 fontsize_i2a = {11:'eleven', 13:'thirteen', 16:'sixteen',
74                 20:'twenty', 26:'twentysix'}
75 fontsize_pt2i = {'11pt':11, '13pt':13, '16pt':16, '20pt':20, '26pt':26}
76
77 begin_mudela_re = re.compile ('^ *\\\\begin{mudela}')
78 begin_verbatim_re = re.compile ('^ *\\\\begin{verbatim}')
79 end_verbatim_re = re.compile ('^ *\\\\end{verbatim}')
80 extract_papersize_re = re.compile('\\\\documentclass[\[, ]*(\w*)paper[\w ,]*\]\{\w*\}')
81 extract_fontsize_re = re.compile('[ ,\[]*([0-9]*)pt')
82 begin_mudela_opts_re = re.compile('\[[^\]]*\]')
83 end_mudela_re = re.compile ('^ *\\\\end{mudela}')
84 section_re = re.compile ('\\\\section')
85 chapter_re = re.compile ('\\\\chapter')
86 input_re = re.compile ('^\\\\input{([^}]*)')
87 include_re = re.compile ('^\\\\include{([^}]*)')
88 begin_document_re = re.compile ('^ *\\\\begin{document}')
89 documentclass_re = re.compile('\\\\documentclass')
90 twocolumn_re = re.compile('\\\\twocolumn')
91 onecolumn_re = re.compile('\\\\onecolumn')
92 preMudelaExample_re = re.compile('\\\\def\\\\preMudelaExample')
93 postMudelaExample_re = re.compile('\\\\def\\\\postMudelaExample')
94 boundingBox_re = re.compile('%%BoundingBox: ([0-9]+) ([0-9]+) ([0-9]+) ([0-9]+)')
95 intertext_re = re.compile("intertext=\"([^\"]*)\"")
96
97 def file_exist_b(name):
98     try: 
99         f = open(name)
100     except IOError:
101         return 0
102     f.close ()
103     return 1
104
105 def ps_dimention(fname):
106     fd = open(fname)
107     lines = fd.readlines()
108     for line in lines:
109         s = boundingBox_re.search(line)
110         if s:
111             break
112     return (int(s.groups()[2])-int(s.groups()[0]), 
113             int(s.groups()[3])-int(s.groups()[1]))
114
115
116 class CompileStatus:
117     pass
118 class SomethingIsSeriouslyBroken:
119     pass
120
121 def file_mtime (name):
122     return os.stat (name)[8] #mod time
123
124 def need_recompile_b(infile, outfile):
125     indate = file_mtime (infile)
126     try:
127         outdate = file_mtime (outfile)
128         return indate > outdate
129     except os.error:
130         return 1
131
132 #
133 # executes os.system(command) if infile is newer than
134 # outfile or outfile don't exist
135 #
136 def compile (command, workingdir, infile, outfile):
137     "Test if infile is newer than outfile. If so, cd to workingdir"
138     "and execute command"
139     indate = file_mtime (workingdir+infile)
140     try:
141         outdate = file_mtime (workingdir+outfile)
142         recompile = indate > outdate
143
144     except os.error:
145         recompile = 1
146
147     if recompile:
148         sys.stderr.write ('invoking `%s\'\n' % command)
149         if workingdir == '':
150             status = os.system (command)
151         else:
152             status = os.system ('cd %s; %s' %(workingdir, command))
153         if status:
154             raise CompileStatus
155
156 class Properties:
157     #
158     # init
159     #
160     def __init__(self):
161         self.__linewidth = {
162             1: {'a4':{10: 345, 11: 360, 12: 390},
163                 'a5':{10: 276, 11: 276, 12: 276},
164                 'b5':{10: 345, 11: 356, 12: 356},
165                 'letter':{10: 345, 11: 360, 12: 390},
166                 'legal': {10: 345, 11: 360, 12: 390},
167                 'executive':{10: 345, 11: 360, 12: 379}},
168             2: {'a4':{10: 167, 11: 175, 12: 190},
169                 'a5':{10: 133, 11: 133, 12: 133},
170                 'b5':{10: 167, 11: 173, 12: 173},
171                 'letter':{10: 167, 11: 175, 12: 190},
172                 'legal':{10: 167, 11: 175, 12: 190},
173                 'executive':{10: 167, 11: 175, 12: 184}}}
174         # >0 --> force all mudela to this pt size
175         self.force_mudela_fontsize = 0
176         self.force_verbatim_b = 0
177         self.__data = {
178             'mudela-fontsize' : {'init': 16},
179             'papersize' : {'init': 'a4'},
180             'num-column' : {'init': 1},
181             'tex-fontsize' : {'init': 10}
182             }
183     def clear_for_new_file(self):
184         for var in self.__data.keys():
185             self.__data[var] = {'init': self.__data[var]['init']}
186     def clear_for_new_block(self):
187         for var in self.__data.keys():
188             if self.__data[var].has_key('block'):
189                 del self.__data[var]['block']
190     def __get_variable(self, var):
191         if self.__data[var].has_key('block'):
192             return self.__data[var]['block']
193         elif self.__data[var].has_key('file'):
194             return self.__data[var]['file']
195         else:
196             return self.__data[var]['init']
197     def setPapersize(self, size, requester):
198         self.__data['papersize'][requester] = size
199     def getPapersize(self):
200         return self.__get_variable('papersize')
201     def setMudelaFontsize(self, size, requester):
202         self.__data['mudela-fontsize'][requester] = size
203     def getMudelaFontsize(self):
204         if self.force_mudela_fontsize:
205             return self.force_mudela_fontsize
206         return self.__get_variable('mudela-fontsize')
207     def setTexFontsize(self, size, requester):
208         self.__data['tex-fontsize'][requester] = size
209     def getTexFontsize(self):
210         return self.__get_variable('tex-fontsize')
211     def setNumColumn(self, num, requester):
212         self.__data['num-column'][requester] = num
213     def getNumColumn(self):
214         return self.__get_variable('num-column')
215     def getLineWidth(self):
216         return self.__linewidth[self.getNumColumn()][self.getPapersize()][self.getTexFontsize()]
217
218
219 class Mudela_output:
220     def __init__ (self, basename):
221         self.basename = basename
222         self.temp_filename = "%s/%s" %(outdir, 'mudela-temp.ly')
223         self.file = open (self.temp_filename, 'w')
224         self.__lines = []
225         # 'tex' or 'eps'
226         self.graphic_type = 'tex'
227         self.code_type = 'unknown'
228         self.code_type_override = None
229     def write (self, line):
230         # match only if there is nothing but whitespace before \begin HACK
231         if re.search('^\s*\\\\begin{mudela}', line):
232             self.scan_begin_statement(line)
233         else:
234             if self.code_type == 'unknown':
235                 if re.search('^\s*\\\\score', line) or \
236                    re.search('^\s*\\\\paper', line) or \
237                    re.search('^\s*\\\\header', line) or \
238                    re.search('^\s*[A-Za-z]*\s*=', line):
239                     self.code_type = 'ly'
240             self.__lines.append(line)
241     def scan_begin_statement(self, line):
242         r  = begin_mudela_opts_re.search(line)
243         if r:
244             o = r.group()[1:-1]
245             optlist =  re.compile('[\s,]*').split(o)
246         else:
247             optlist = []
248         if 'fragment' in optlist:
249             self.code_type_override = 'fly'
250         if 'nonfragment' in optlist:
251             self.code_type_override = 'ly'
252         if 'eps' in optlist:
253             self.graphic_type = 'eps'
254         for pt in fontsize_pt2i.keys():
255             if pt in optlist:
256                 Props.setMudelaFontsize(fontsize_pt2i[pt], 'block')
257     def write_red_tape(self):
258         self.file.write ('\\include \"paper%d.ly\"\n' \
259                          % Props.getMudelaFontsize())
260                          
261         s = fontsize_i2a[Props.getMudelaFontsize()]
262         if self.code_type == 'fly':
263             linewidth_str = 'linewidth = -1.\cm;'
264         else:
265             linewidth_str = 'linewidth = %i.\\pt;' % Props.getLineWidth()
266         self.file.write("\\paper {"
267                         + "\\paper_%s " % s
268                         + linewidth_str
269                         + "castingalgorithm = \Gourlay; \n}")
270                         #+ "castingalgorithm = \Wordwrap; indent = 2.\cm; \n}")
271         if self.code_type == 'fly':
272             self.file.write('\\score{\n\\notes{')
273     def close (self):
274         if self.code_type == 'unknown':
275             self.code_type = 'fly'
276         if self.code_type_override:
277             self.code_type = self.code_type_override
278         self.write_red_tape()
279         for l in self.__lines:
280             self.file.write(l)
281         if self.code_type == 'fly':
282             self.file.write('}}')
283             
284         self.file.close()
285
286         inf = outdir + self.basename + '.ly'
287         outf = outdir + self.basename + '.tex'
288         if not os.path.isfile(inf):
289             status = 1
290         else:
291             status = os.system ('diff -q %s %s' % (self.temp_filename, inf))
292         if status:
293             os.rename (self.temp_filename, inf)
294         if need_recompile_b(inf, outf):
295             out_files.append((self.graphic_type, inf))
296     def insert_me_string(self):
297         "Returns a string that can be used directly in latex."
298         if self.graphic_type == 'tex':
299             return ['tex', self.basename]
300         elif self.graphic_type == 'eps':
301             return ['eps', self.basename]
302         else:
303             raise SomethingIsSeriouslyBroken
304
305 class Tex_output:
306     def __init__ (self, name):
307         self.output_fn = '%s/%s' % (outdir, name)
308         self.__lines = []
309     def open_verbatim (self, line, level):
310         self.__lines.append('\\begin{verbatim}\n')
311         if level == 2:
312             s = re.sub('veryverbatim[\s,]*', '', line)
313             s = re.sub('intertext=\"([^\"]*)\"[\s,]*', '', s)
314             s = re.sub(',\s*\]', ']', s)
315             s = re.sub('\[\]', '', s)
316             self.__lines.append(s);
317     def close_verbatim (self):
318         self.__lines.append('\\end{verbatim}\n')
319     def write (self, s):
320         self.__lines.append(s)
321     def create_graphics(self):
322         s = ''
323         g_vec = []
324         for line in self.__lines:
325             if type(line)==type([]):
326                 g_vec.append(line)
327         for g in g_vec:
328             if need_recompile_b(outdir+g[1]+'.ly', outdir+g[1]+'.tex'):
329                     s = s + ' ' + g[1]+'.ly'
330         if s != '':
331             e = os.system('cd %s; lilypond %s' %(outdir, s))
332             if e:
333                 print "error: lilypond exited with value", e
334                 sys.exit(e)
335         for g in g_vec:
336             if g[0] == 'eps':
337                 compile('tex %s' % g[1]+'.tex', outdir, g[1]+'.tex', g[1]+'.dvi')
338                 compile('dvips -E -o %s %s' %(g[1]+'.eps', g[1]+'.dvi'), outdir,
339                         g[1]+'.dvi', g[1]+'.eps')
340     def write_outfile(self):
341         file = open(self.output_fn+'.latex', 'w')
342         file.write('% Created by mudela-book\n')
343         for line in self.__lines:
344             if type(line)==type([]):
345                 if line[0] == 'tex':
346                     file.write('\\preMudelaExample\\input %s\n\postMudelaExample '\
347                                # TeX applies the prefix of the main source automatically.
348                                % (line[1]+'.tex'))
349 #                               % (outdir+line[1]+'.tex'))
350                 if line[0] == 'eps':
351                     ps_dim = ps_dimention(outdir+line[1]+'.eps')
352                     file.write('\\parbox{%ipt}{\includegraphics{%s}}\n' \
353                                % (ps_dim[0], line[1]+'.eps'))
354 #                               % (ps_dim[0], outdir+line[1]+'.eps'))
355             else:
356                 file.write(line)
357         file.close()
358
359 # given parameter s="\mudela[some options]{CODE} some text and commands"
360 # it returns a tuple:
361 #    (CODE, integer)
362 # where the last number is the index of the ending '}'
363 def extract_command(s):
364     start_found_b = 0
365     count = 0
366     start = 0
367     for idx in range(len(s)):
368         if s[idx] == '{':
369             if not start_found_b:
370                 start = idx
371                 start_found_b = 1
372             count = count + 1
373         if s[idx] == '}':
374             count = count - 1
375         if (start_found_b == 1) and (count == 0):
376             break
377     return s[start+1:idx], idx
378
379 class Tex_input:
380     def __init__ (self, filename):
381         for fn in [filename, filename+'.tex', filename+'.doc']:
382             try:
383                 self.infile = open (fn)
384                 self.filename = fn
385                 return
386             except:
387                 continue
388         raise IOError
389     def get_lines (self):
390         lines = self.infile.readlines ()
391         (retlines, retdeps) = ([],[self.filename])
392         for line in lines:
393             r_inp = input_re.search (line)
394             r_inc = include_re.search (line)
395
396             # Filename rules for \input :
397             # input: no .tex ext
398             # 1. will search for file with exact that name (tex-input.my will be found)
399             # 2. will search for file with .tex ext, (tex-input.my
400             #    will find tex-input.my.tex)
401             # input: with .tex ext
402             # 1. will find exact match
403             
404             # Filename rules for \include :
405             # 1. will only find files with name given to \include + .tex ext
406             if r_inp:
407                 try:
408                     t = Tex_input (r_inp.groups()[0])
409                     ls = t.get_lines ()
410                     retlines = retlines + ls[0]
411                     retdeps = retdeps + ls[1]
412                 except:
413                     print "warning: can't find %s, let's hope latex will" \
414                           % r_inp.groups()[0]
415                     retlines.append (line)
416             elif r_inc:
417                 try:
418                     t = Tex_input (r_inc.groups()[0]+'.tex')
419                     ls =t.get_lines ()
420                     ls[0].insert(0, '\\newpage\n')
421                     ls[0].append('\\newpage\n')
422                     retlines = retlines + ls[0]
423                     retdeps = retdeps + ls[1]
424                 except:
425                     print "warning: can't find %s, let's hope latex will" \
426                           % r_inc.groups()[0]
427                     retlines.append (line)
428             else:
429                 # This code should be rewritten, it looks terrible
430                 r_mud = defined_mudela_cmd_re.search(line)
431                 if r_mud:
432                     ss = "\\\\verb(?P<xx>[^a-zA-Z])\s*\\\\%s\s*(?P=xx)" \
433                          % re.escape(r_mud.group()[1:])
434                     # just append the line if the command is inside \verb|..|
435                     if re.search(ss, line):
436                         retlines.append(line)
437                         continue
438                     while 1:
439                         opts = r_mud.groups()[2]
440                         cmd_start_idx = r_mud.span()[0]
441                         if cmd_start_idx > 0:
442                             retlines.append(line[:cmd_start_idx])
443                             
444                         cmd_data, rest_idx = extract_command(line[cmd_start_idx:])
445                         rest_idx = rest_idx + cmd_start_idx + 1
446                         if opts == None:
447                             opts = ''
448                         else:
449                             opts = ', '+opts
450                         
451                         v = string.split(defined_mudela_cmd[r_mud.groups()[0]], '\n')
452                         for l in v[1:-1]:
453                             l = string.replace(l, '\\fontoptions', opts)
454                             l = string.replace(l, '\\maininput', cmd_data)
455                             retlines.append(l)
456                         r_mud = defined_mudela_cmd_re.search(line[rest_idx:])
457                         if not r_mud:
458                             rs = line[rest_idx:]
459                             while rs[0] == " ":
460                                 rs = rs[1:]
461                             if rs != "\n":
462                                 retlines.append(line[rest_idx:])
463                             break;
464                         line = line[rest_idx:]
465                 else:
466                     retlines.append (line)
467         return (retlines, retdeps)
468
469
470 class Main_tex_input(Tex_input):
471     def __init__ (self, name, outname):
472
473         Tex_input.__init__ (self, name) # ugh
474         self.outname = outname
475         self.chapter = 0
476         self.section = 0
477         self.fine_count =0
478         self.mudtex = Tex_output (self.outname)
479         self.mudela = None
480         self.deps = []
481         self.verbatim = 0
482         # set to 'mudela' when we are processing mudela code,
483         # both verbatim and graphic-to-be
484         self.mode = 'latex'
485     def set_sections (self, l):
486         if section_re.search (l):
487             self.section = self.section + 1
488         if chapter_re.search (l):
489             self.section = 0
490             self.chapter = self.chapter + 1
491
492     def gen_basename (self):
493         return '%s-%d.%d.%d' % (self.outname, self.chapter,
494                                 self.section, self.fine_count)
495     def extract_papersize_from_documentclass(self, line):
496         pre = extract_papersize_re.search(line)
497         if not pre:
498             return None
499         return pre.groups()[0]
500     def extract_fontsize_from_documentclass(self, line):
501         r = extract_fontsize_re.search(line)
502         if r:
503             return int(r.groups()[0])
504     def do_it(self):
505         preMudelaDef = postMudelaDef = 0
506         (lines, self.deps) = self.get_lines ()
507         #HACK
508         latex_verbatim = 0
509         for line in lines:
510             if documentclass_re.search (line):
511                 p = self.extract_papersize_from_documentclass (line)
512                 if p:
513                     Props.setPapersize(p, 'file')
514                 f = self.extract_fontsize_from_documentclass (line)
515                 if f:
516                     Props.setTexFontsize (f, 'file')
517             elif twocolumn_re.search (line):
518                 Props.setNumColumn (2, 'file')
519             elif onecolumn_re.search (line):
520                 Props.setNumColumn (1, 'file')
521             elif preMudelaExample_re.search (line):
522                 preMudelaDef = 1
523             elif postMudelaExample_re.search (line):
524                 postMudelaDef = 1
525             elif begin_verbatim_re.search (line):
526                 latex_verbatim = 1
527             elif end_verbatim_re.search (line):
528                 latex_verbatim = 0
529             elif begin_document_re.search (line):
530                 if not preMudelaDef:
531                     self.mudtex.write ('\\def\\preMudelaExample{}\n')
532                 if not postMudelaDef:
533                     self.mudtex.write ('\\def\\postMudelaExample{}\n')
534             elif begin_mudela_re.search (line) and not latex_verbatim:
535                 Props.clear_for_new_block()
536                 if __debug__:
537                     if self.mode == 'mudela':
538                         raise AssertionError
539                 self.mode = 'mudela'
540                 r  = begin_mudela_opts_re.search (line)
541                 if r:
542                     o = r.group()[1:][:-1]
543                     optlist =  re.compile('[ ,]*').split(o)
544                     m = intertext_re.search(r.group())
545                     if m:
546                         self.intertext = m.groups()[0]
547                     else:
548                         self.intertext = None
549                 else:
550                     optlist = []
551                 if ('veryverbatim' in optlist):
552                     self.verbatim = 2
553                 elif ('verbatim' in optlist) or (Props.force_verbatim_b):
554                     self.verbatim = 1
555                 else:
556                     self.verbatim = 0
557                 if self.verbatim:
558                     self.mudtex.open_verbatim (line, self.verbatim)
559                 self.mudela = Mudela_output (self.gen_basename ())
560                 self.mudela.write (line)
561                 continue
562             elif end_mudela_re.search (line) and not latex_verbatim:
563                 if __debug__:
564                     if self.mode != 'mudela':
565                         raise AssertionError
566
567                 if self.verbatim:
568                     if self.verbatim == 2:
569                         self.mudtex.write (line)
570                     self.mudtex.close_verbatim ()
571                 self.mudela.close ()
572                 if self.verbatim and self.intertext:
573                     self.mudtex.write(self.intertext)
574                 self.mudtex.write (self.mudela.insert_me_string())
575                 del self.mudela
576                 self.mudela = None
577                 self.fine_count = self.fine_count + 1
578                 self.mode = 'latex'
579                 continue
580
581             if self.mode == 'mudela':
582                 self.mudela.write (line)
583                 if self.verbatim:
584                     self.mudtex.write (line)
585             else:
586                 self.mudtex.write (line)
587                 self.set_sections(line)
588         self.mudtex.create_graphics()
589         self.mudtex.write_outfile()
590         del self.mudtex
591                 
592
593 def help():
594     sys.stdout.write("""Usage: mudela-book [options] FILE\n
595 Generate hybrid LaTeX input from Latex + mudela
596 Options:\n
597   -h, --help                     print this help
598   -d, --outdir=DIR               directory to put generated files
599   -o, --outname=FILE             prefix for filenames
600   --default-mudela-fontsize=??pt default fontsize for music
601   --force-mudela-fontsize=??pt   force fontsize for all inline mudela
602   --force-verbatim               make all mudela verbatim\n
603   --dependencies                 write dependencies
604   --init                         mudela-book initfile
605   """
606                      )
607     sys.exit (0)
608
609
610 def write_deps (fn, out,  deps):
611         out_fn = outdir + '/' + fn
612         print '`writing `%s\'\n\'' % out_fn
613         
614         f = open (out_fn, 'w')
615         f.write ('%s: %s\n'% (outdir + '/' + out + '.dvi',
616                               reduce (lambda x,y: x + ' '+ y, deps)))
617         f.close ()
618
619 def identify():
620     sys.stderr.write ('This is %s version %s\n' % ('mudela-book', program_version))
621
622 def main():
623     global outdir, initfile, defined_mudela_cmd, defined_mudela_cmd_re
624     outname = ''
625     try:
626         (options, files) = getopt.getopt(
627             sys.argv[1:], 'hd:o:', ['outdir=', 'outname=',
628                                     'default-mudela-fontsize=',
629                                     'force-mudela-fontsize=',
630                                     'help', 'dependencies',
631                                     'force-verbatim', 'init='])
632     except getopt.error, msg:
633         print "error:", msg
634         sys.exit(1)
635         
636     do_deps = 0
637     for opt in options:    
638         o = opt[0]
639         a = opt[1]
640         if o == '--outname' or o == '-o':
641             if len(files) > 1:
642                 #HACK
643                 print "Mudela-book is confused by --outname on multiple files"
644                 sys.exit(1)
645             outname = a
646         if o == '--outdir' or o == '-d':
647             outdir = a
648         if o == '--help' or o == '-h':
649             help ()
650         if o == '--dependencies':
651             do_deps = 1
652         if o == '--default-mudela-fontsize':
653             if not fontsize_pt2i.has_key(a):
654                 print "Error: illegal fontsize:", a
655                 print " accepted fontsizes are: 11pt, 13pt, 16pt, 20pt, 26pt"
656                 sys.exit()
657             Props.setMudelaFontsize(fontsize_pt2i[a], 'init')
658         if o == '--force-mudela-fontsize':
659             if not fontsize_pt2i.has_key(a):
660                 print "Error: illegal fontsize:", a
661                 print " accepted fontsizes are: 11pt, 13pt, 16pt, 20pt, 26pt"
662                 sys.exit()
663             Props.force_mudela_fontsize = fontsize_pt2i[a]
664         if o == '--force-verbatim':
665             Props.force_verbatim_b = 1
666         if o == '--init':
667             initfile =  a
668     if outdir[-1:] != '/':
669         outdir = outdir + '/'
670
671     defined_mudela_cmd = {'mudela': r"""
672 \begin{mudela}[eps \fontoptions]
673   \type Staff <
674     \type Voice{
675       \maininput
676     }
677   >
678 \end{mudela}
679 """}
680     if initfile != '':
681         f = open(initfile)
682         s = f.read()
683         f.close()
684         d = eval(s)
685         for i in d.keys():
686             defined_mudela_cmd[i] = d[i]
687         del d
688     c = defined_mudela_cmd.keys()[0]
689     for x in defined_mudela_cmd.keys()[1:]:
690         c = c + '|'+x
691     defined_mudela_cmd_re = re.compile("\\\\(%s)(\[(\d*pt)\])*{([^}]*)}" %c)
692
693     if not os.path.isdir(outdir):
694         os.system('mkdir %s' % outdir)
695
696     for input_filename in files:
697         Props.clear_for_new_file()
698         if outname:
699             my_outname = outname
700         else:
701             my_outname = os.path.basename(os.path.splitext(input_filename)[0])
702         my_depname = my_outname + '.dep'        
703         inp = Main_tex_input (input_filename, my_outname)
704         inp.do_it ()
705 #        os.system('latex %s/%s.latex' % (outdir, my_outname))
706         if do_deps:
707             write_deps (my_depname, my_outname, inp.deps)
708
709 identify()
710 Props = Properties()
711 main()