2 # All non-english comments are NOT in swedish, they are norwegian!
4 # TODO: center option (??)
5 # * One empty, not two line after a mudela{floating} should be enough
6 # to get a new paragraph.
7 # * clean up handling of filename of inputfile
8 # * the verbatim option should not be visible in the created latex file
9 # * what the h.. does castingalgorithm do/mean???
10 # * the following fails because mudelabook doesn't care that the
11 # last } after \end{mudela} finishes the marginpar:
13 # \begin{mudela}[fragment]
21 # much rewritten by new author. I think the work has been split more
22 # logical between different classes.
33 program_version = '0.4'
34 default_paper_size_global = 'a4'
35 default_mudela_fontsize = '16pt'
36 force_mudela_fontsize_b = 0
41 fontsize_i2a = {11:'eleven', 13:'thirteen', 16:'sixteen', 20:'twenty', 26:'twentysix'}
42 fontsize_pt2i = {'11pt':11, '13pt':13, '16pt':16, '20pt':20, '26pt':26}
44 begin_mudela_re = re.compile ('^ *\\\\begin{mudela}')
45 begin_mudela_opts_re = re.compile('\[[^\]]*\]')
46 end_mudela_re = re.compile ('^ *\\\\end{mudela}')
47 section_re = re.compile ('\\\\section')
48 chapter_re = re.compile ('\\\\chapter')
49 input_re = re.compile ('^\\\\input{([^}]*)')
50 include_re = re.compile ('^\\\\include{([^}]*)')
51 begin_document_re = re.compile ('^ *\\\\begin{document}')
52 documentclass_re = re.compile('\\\\documentclass')
53 twocolumn_re = re.compile('\\\\twocolumn')
54 onecolumn_re = re.compile('\\\\onecolumn')
55 preMudelaExample_re = re.compile('\\\\def\\\\preMudelaExample')
56 postMudelaExample_re = re.compile('\\\\def\\\\postMudelaExample')
57 boundingBox_re = re.compile('%%BoundingBox: ([0-9]*) ([0-9]*) ([0-9]*) ([0-9]*)')
59 def file_exist_b(name):
67 def ps_dimention(fname):
69 lines = fd.readlines()
71 s = boundingBox_re.search(line)
74 return (int(s.groups()[2])-int(s.groups()[0]),
75 int(s.groups()[3])-int(s.groups()[1]))
81 def file_mtime (name):
82 return os.stat (name)[8] #mod time
84 def need_recompile_b(infile, outfile):
85 indate = file_mtime (infile)
87 outdate = file_mtime (outfile)
88 return indate > outdate
94 # executes os.system(command) if infile is newer than
95 # outfile or outfile don't exist
97 def compile (command, workingdir, infile, outfile):
98 indate = file_mtime (workingdir+infile)
100 outdate = file_mtime (workingdir+outfile)
101 recompile = indate > outdate
107 sys.stderr.write ('invoking `%s\'\n' % command)
109 status = os.system (command)
111 status = os.system ('cd %s; %s' %(workingdir, command))
117 __onecolumn_linewidth = {
118 'a4':{'10pt': 345, '11pt': 360, '12pt':390},
119 'a5':{'10pt': 276, '11pt': 276, '12pt':276},
120 'b5':{'10pt': 345, '11pt': 356, '12pt':356},
121 'letter':{'10pt': 345, '11pt': 360, '12pt':390},
122 'legal':{'10pt': 345, '11pt': 360, '12pt':390},
123 'executive':{'10pt': 345, '11pt': 360, '12pt':379}
125 __twocolumn_linewidth = {
126 'a4':{'10pt': 167, '11pt': 175, '12pt':190},
127 'a5':{'10pt': 133, '11pt': 133, '12pt':133},
128 'b5':{'10pt': 167, '11pt': 173, '12pt':173},
129 'letter':{'10pt': 167, '11pt': 175, '12pt':190},
130 'legal':{'10pt': 167, '11pt': 175, '12pt':190},
131 'executive':{'10pt': 167, '11pt': 175, '12pt':184}
139 self.__papersize = default_paper_size_global
140 def set_papersize (self, p):
141 if not self.__onecolumn_linewidth.has_key(p):
142 print "warning:unsupported papersize", p, \
143 "will use", default_paper_size_global
144 self.__papersize = default_paper_size_global
147 def set_latex_fontsize(self, pt):
149 def get_linewidth (self):
150 if self.__numcolumn == 1:
151 return self.__onecolumn_linewidth[self.__papersize][self.__fontsize]
153 return self.__twocolumn_linewidth[self.__papersize][self.__fontsize]
154 def onecolumn (self):
156 def twocolumn (self):
161 def __init__ (self, basename):
162 self.basename = basename
164 self.feta_pt_size = fontsize_pt2i[default_mudela_fontsize]
165 self.temp_filename = "%s/%s" %(outdir, 'mudela-temp.ly')
166 self.file = open (self.temp_filename, 'w')
168 self.graphic_type = 'tex'
170 def write (self, line):
171 # match only if there is nothing but whitespace before \begin
172 if re.search('^\s*\\\\begin{mudela}', line):
173 self.scan_begin_statement(line)
174 self.write_red_tape()
176 self.file.write (line)
177 def scan_begin_statement(self, line):
178 global force_mudela_fontsize_b;
179 r = begin_mudela_opts_re.search(line)
181 o = r.group()[1:][:-1]
182 optlist = re.compile('[ ,]*').split(o)
185 if 'floating' in optlist:
186 self.graphic_type = 'eps'
188 self.graphic_type = 'tex'
189 if 'fragment' in optlist:
193 for pt in fontsize_pt2i.keys():
195 if force_mudela_fontsize_b:
196 self.feta_pt_size = fontsize_pt2i[default_mudela_fontsize]
198 self.feta_pt_size = fontsize_pt2i[pt]
199 def write_red_tape(self):
200 self.file.write ('\\include \"paper%d.ly\"\n' % self.feta_pt_size)
201 s = fontsize_i2a[self.feta_pt_size]
203 self.file.write("default_paper = \\paper {"
204 + "\\paper_%s\n linewidth = -1.\\pt;" % s
205 + "castingalgorithm = \Wordwrap; indent = 2.\cm; \n}")
206 self.file.write("\\score{\n\\notes{") #HACK
208 self.file.write ("default_paper = \\paper {"
209 + "\\paper_%s\n linewidth = %i.\\pt;" % \
210 (s, Paper.get_linewidth()) \
211 + "castingalgorithm = \Wordwrap; indent = 2.\cm;\n}")
214 self.file.write ('}\\paper { \\default_paper; } }\n')
217 inf = self.basename + '.ly'
218 outf = self.basename + '.tex'
219 if not file_exist_b (inf):
222 status = os.system ('diff -q %s %s' % (self.temp_filename, inf))
224 os.rename (self.temp_filename, inf)
226 if need_recompile_b(inf, outf):
227 print "Need recompile"
228 out_files.append((self.graphic_type, inf))
230 compile ('lilypond -o %s %s;'% (self.basename, inf), '', inf, outf)
231 if self.graphic_type == 'eps':
232 bname = self.basename[string.rfind(self.basename, '/')+1:]
233 tex_name = bname+'.tex'
234 dvi_name = bname+'.dvi'
235 eps_name = bname+'.eps'
236 compile ('tex %s' % tex_name, outdir, tex_name, dvi_name)
237 compile ('dvips -E -o %s %s' % (eps_name, dvi_name), outdir, dvi_name, eps_name)
238 def insert_me_string(self):
239 "Returns a string that can be used directly in latex."
240 if self.graphic_type == 'tex':
241 return '\\preMudelaExample\\input %s\n\postMudelaExample\n' % self.basename
242 elif self.graphic_type == 'eps':
243 ps_dim = ps_dimention('%s.eps' % self.basename)
244 return '\\parbox{%ipt}{\includegraphics{%s.eps}}' % (ps_dim[0], self.basename)
246 print "Unsupported graphic type '%s'" % self.graphic_type
250 def __init__ (self, name):
251 self.output_fn = '%s/%s' % (outdir, name)
252 self.file = open (self.output_fn , 'w')
253 def open_mudela (self, basename):
254 self.mudela_basename = basename
255 def open_verbatim (self):
256 self.file.write ('\\begin{verbatim}\n')
257 def close_verbatim (self):
258 self.file.write ('\\end{verbatim}\n')
263 def __init__ (self,name):
267 self.infile = open (name)
269 if (name[-4:] != '.tex') and (name[-4:] != '.doc'):
272 self.infile = open (name)
275 self.infile = open(name)
278 def get_lines (self):
279 lines = self.infile.readlines ()
280 (retlines, retdeps) = ([],[self.filename])
282 r = input_re.search (line)
283 ri = include_re.search (line)
286 t = Tex_input (r.groups()[0])
289 # HACK should not warn about files like lilyponddefs, only
290 # files we think is a part of the document and include
291 # mudela that need parsing
292 print "warning: can't find file " % r.grops()[0]
294 retlines = retlines + ls[0]
295 retdeps = retdeps + ls[1]
298 t = Tex_input (ri.groups()[0])
300 ls[0].insert(0, '\\newpage')
301 ls[0].append('\\newpage')
303 print "warning: can't find include file:", ri.groups()[0]
305 retlines = retlines + ls[0]
306 retdeps = retdeps + ls[1]
308 retlines.append (line)
309 return (retlines, retdeps)
312 class Main_tex_input(Tex_input):
313 def __init__ (self, name, outname):
315 Tex_input.__init__ (self, name) # ugh
317 self.outname = outname
321 self.mudtex = Tex_output (self.outname)
325 # set to 'mudela' when we are processing mudela code,
326 # both verbatim and graphic-to-be
328 def set_sections (self, l):
329 if section_re.search (l):
330 self.section = self.section + 1
331 if chapter_re.search (l):
333 self.chapter = self.chapter + 1
335 def gen_basename (self):
336 return '%s/%s-%d.%d.%d' % (outdir, self.outname,self.chapter,self.section,self.fine_count)
338 def extract_papersize_from_documentclass(self, line):
339 pre = re.search('\\\\documentclass[\[, ]*(\w*)paper[\w ,]*\]\{\w*\}', line)
341 return default_paper_size_global
342 return pre.groups()[0]
343 def extract_fontsize_from_documentclass(self, line):
344 if re.search('\\\\documentclass\[[^\]]*\]\{[^\}]*\}', line):
345 r = re.search('[ ,\[]*([0-9]*pt)', line)
350 preMudelaDef = postMudelaDef = 0
351 (lines, self.deps) = self.get_lines ()
353 if documentclass_re.search (line):
354 Paper.set_papersize (self.extract_papersize_from_documentclass (line) )
355 Paper.set_latex_fontsize (self.extract_fontsize_from_documentclass (line) )
356 elif twocolumn_re.search (line):
358 elif onecolumn_re.search (line):
360 elif preMudelaExample_re.search (line):
362 elif postMudelaExample_re.search (line):
364 elif begin_document_re.search (line):
366 self.mudtex.write ('\\def\\preMudelaExample{}\n')
367 if not postMudelaDef:
368 self.mudtex.write ('\\def\\postMudelaExample{}\n')
369 elif begin_mudela_re.search (line):
371 if self.mode == 'mudela':
374 r = begin_mudela_opts_re.search (line)
376 o = r.group()[1:][:-1]
377 optlist = re.compile('[ ,]*').split(o)
380 if 'verbatim' in optlist:
382 self.mudtex.open_verbatim ()
385 self.mudela = Mudela_output (self.gen_basename ())
387 elif end_mudela_re.search (line):
389 if self.mode != 'mudela':
393 self.mudtex.write (self.mudela.insert_me_string())
396 self.fine_count = self.fine_count + 1
398 self.mudtex.write (line)
399 self.mudtex.close_verbatim ()
403 if self.mode == 'mudela' and not self.verbatim:
404 self.mudela.write (line)
406 self.mudtex.write (line)
407 self.set_sections(line)
412 sys.stdout.write("Usage: mudela-book [options] FILE\n"
413 + "Generate hybrid LaTeX input from Latex + mudela"
415 + " -h, --help print this help\n"
416 + " -d, --outdir=DIR directory to put generated files\n"
417 + " -o, --outname=FILE prefix for filenames\n"
418 + " --mudela-fontsize=??pt default fontsize when no parameter for \\begin{mudela}\n"
419 + " --force-mudela-fontsize=??pt force fontsize for all inline mudela\n"
424 def write_deps (fn, out, deps):
425 out_fn = outdir + '/' + fn
426 print '\`writing \`%s\'\n\'' % out_fn
428 f = open (out_fn, 'w')
429 f.write ('%s: %s\n'% (outdir + '/' + out + '.dvi',
430 reduce (lambda x,y: x + ' '+ y, deps)))
434 sys.stderr.write('*** Lokal versjon av mudela-book ***\n')
435 sys.stderr.write ('This is %s version %s\n' % ('mudela-book', program_version))
438 global default_mudela_fontsize, force_mudela_fontsize_b, outdir
441 (options, files) = getopt.getopt(
442 sys.argv[1:], 'hd:o:', ['outdir=', 'outname=', 'mudela-fontsize=',
443 'force-mudela-fontsize=', 'help', 'dependencies'])
444 except getopt.error, msg:
452 if o == '--outname' or o == '-o':
454 if o == '--outdir' or o == '-d':
456 if o == '--help' or o == '-h':
458 if o == '--dependencies':
460 if o == '--mudela-fontsize':
461 default_mudela_fontsize = a
462 if o == '--force-mudela-fontsize':
463 default_mudela_fontsize = a
464 force_mudela_fontsize_b = 1
466 if outdir[-1:] != '/':
467 outdir = outdir + '/'
469 if not file_exist_b(outdir):
470 os.system('mkdir %s' % outdir)
472 if not fontsize_pt2i.has_key(default_mudela_fontsize):
473 print "warning: fontsize %s is not supported using 16pt" % default_mudela_fontsize
474 default_mudela_fontsize = '16pt'
479 my_outname = regsub.sub ('\\(.*\\)\\.doc', '\\1', f)
481 my_depname = my_outname + '.dep'
483 inp = Main_tex_input (f, my_outname)
487 write_deps (my_depname, my_outname, inp.deps)
495 print "outfile:", out_files
497 print "skal gjøre", i