+ if not str:
+ error ("File not found `%s'\n" % filename)
+
+ retdeps = [filename]
+
+ if __main__.format == '':
+ latex = re.search ('\\\\document', str[:200])
+ texinfo = re.search ('@node', str[:200])
+ if (texinfo and latex) or not (texinfo or latex):
+ error("error: can't determine format, please specify")
+ if texinfo:
+ __main__.format = 'texi'
+ else:
+ __main__.format = 'latex'
+
+ chunks = [('input', str)]
+
+ for func in (find_verbatim_chunks, find_verb_chunks, find_include_chunks, find_input_chunks):
+ newchunks = []
+ for c in chunks:
+ if c[0] == 'input':
+ ch = func (c[1])
+ newchunks = newchunks + ch
+ else:
+ newchunks.append (c)
+ chunks = newchunks
+
+ return chunks
+
+
+
+def scan_preamble (str):
+ options = []
+ m = get_re ('header').search( str)
+
+ # should extract paper & fontsz.
+ if m and m.group (1):
+ options = options + re.split (',[\n \t]*', m.group(1)[1:-1])
+
+ def verbose_fontsize ( x):
+ # o ??
+ #if o.match('[0-9]+pt'):
+ if re.match('[0-9]+pt', x):
+ return 'latexfontsize=' + x
+ else:
+ return x
+
+ options = map (verbose_fontsize, options)
+
+ return options
+
+
+def completize_preamble (str):
+ m = get_re ('preamble-end').search( str)
+ if not m:
+ return str
+
+ preamble = str [:m.start (0)]
+ str = str [m.start(0):]
+
+ if not get_re('def-post-re').search (preamble):
+ preamble = preamble + get_output('output-default-post')
+ if not get_re ('def-pre-re').search( preamble):
+ preamble = preamble + get_output ('output-default-pre')
+
+ # UGH ! BUG!
+ #if re.search ('\\\\includegraphics', str) and not re.search ('usepackage{graphics}',str):
+
+ preamble = preamble + '\\usepackage{graphics}\n'
+
+ return preamble + str
+
+def find_verbatim_chunks (str):
+ """Chop STR into a list of tagged chunks, ie. tuples of form
+ (TYPE_STR, CONTENT_STR), where TYPE_STR is one of 'input' and 'verbatim'
+ """
+
+ chunks = []
+ while str:
+ m = get_re ('verbatim').search( str)
+ if m == None:
+ chunks.append( ('input', str))
+ str = ''
+ else:
+ chunks.append (('input', str[:m.start (0)]))
+ chunks.append (('verbatim', m.group (0)))
+
+ str = str [m.end(0):]
+
+ return chunks
+
+def find_verb_chunks (str):
+
+ chunks = []
+ while str:
+ m = get_re ("verb").search(str)
+ if m == None:
+ chunks.append (('input', str))
+ str = ''
+ else:
+ chunks.append (('input', str[:m.start (0)]))
+ chunks.append (('verbatim', m.group (0)))
+ str = str [m.end(0):]
+
+ return chunks
+
+
+
+def find_mudela_shorthand_chunks (str):
+ return [('input', find_mudela_shorthands(str))]
+
+def find_mudela_shorthands (b):
+ def mudela_short (match):
+ "Find \mudela{}, and substitute appropriate \begin / \end blocks."
+ opts = match.group (1)
+ if opts:
+ opts = ',' + opts[1:-1]
+ else:
+ opts = ''
+ return get_output ('output-mudela-fragment') % (opts, match.group (2))
+
+ def mudela_file (match):
+ "Find \mudelafile, and substitute appropriate \begin / \end blocks."
+ d = [] #, d = retdeps
+ full_path = find_file (match.group (2))
+ if not full_path:
+ error("error: can't find file `%s'\n" % match.group(2))
+
+ d.append (full_path)
+ f = open (full_path)
+ str = f.read (-1)
+ opts = match.group (1)
+ if opts:
+ opts = opts[1:-1]
+ opts = re.split (',[ \n\t]*', opts)
+ else:
+ opts = []
+
+ if re.search ('.fly$', full_path):
+ opts.append ('fly')
+ elif re.search ('.sly$', full_path):
+ opts = opts + [ 'fly','fragment']
+ elif re.search ('.ly$', full_path):
+ opts .append ('nofly')
+
+ str_opts = string.join (opts, ',')
+
+ str = ("%% copied from file `%s'\n" % full_path) + str
+ return get_output ('output-mudela') % (str_opts, str)
+
+ b = get_re('mudela-file').sub (mudela_file, b)
+ b = get_re('mudela').sub (mudela_short, b)
+ return b
+
+def find_mudela_chunks (str):
+ """Find mudela blocks, while watching for verbatim. Returns
+ (STR,MUDS) with substituted for the blocks in STR,
+ and the blocks themselves MUDS"""
+
+ chunks = []
+ while str:
+ m = get_re ("mudela-block").search( str)
+ if not m:
+ chunks.append (('input', str))
+ str = ''
+ break
+
+ chunks.append (('input', str[:m.start (0)]))
+
+ opts = m.group (1)
+ if opts:
+ opts = opts[1:-1]
+ else:
+ opts = ''
+ optlist = get_re('comma-sep').split (opts)
+
+ body = m.group (2)
+ chunks.append (('mudela', body, optlist))
+
+ str = str [m.end (0):]
+
+ return chunks
+
+
+
+def advance_counters (counter, opts, str):
+ """Advance chap/sect counters,
+ revise OPTS. Return the new counter tuple"""
+
+ (chapter, section, count) = counter
+ done = ''
+ while str:
+ m = get_re ('interesting-cs').search(str)
+ if not m:
+ done = done + str
+ str = ''
+ break
+
+ done = done + str[:m.end (0)]
+ str = str[m.end(0):]
+ g = m.group (1)
+
+ if g == 'twocolumn':
+ opts.append ('twocolumn')
+ elif g == 'onecolumn':
+ try:
+ current_opts.remove ('twocolumn')
+ except IndexError:
+ pass
+ elif g == 'chapter':
+ (chapter, section, count) = (chapter + 1, 0, 0)
+ elif g == 'section':
+ (section, count) = (section + 1, 0)
+
+
+ return (chapter, section, count)
+
+
+def schedule_mudela_block (base, chunk, extra_opts):
+ """Take the body and options from CHUNK, figure out how the
+ real .ly should look, and what should be left MAIN_STR (meant
+ for the main file). The .ly is written, and scheduled in
+ TODO.
+
+ Return: a chunk (TYPE_STR, MAIN_STR, OPTIONS, TODO, BASE)
+
+ TODO has format [basename, extension, extension, ... ]
+
+ """
+
+ (type, body, opts) = chunk
+ assert type == 'mudela'
+ opts = opts + extra_opts
+
+ newbody = ''
+ if 'verbatim' in opts:
+ newbody = output_verbatim (body)
+
+ file_body = compose_full_body (body, opts)
+ basename = base
+ if __main__.use_hash:
+ basename = `hash (file_body)`
+ updated = update_file (file_body, basename + '.ly')
+ todo = [basename] # UGH.
+
+ if not os.path.isfile (basename + '.tex') or updated:
+ todo.append ('tex')
+ updated = 1
+
+ for o in opts:
+ m = re.search ('intertext="(.*?)"', o)
+ if m:
+ newbody = newbody + m.group (1)
+
+ if format == 'texi':
+ opts.append ('png')
+
+ if 'png' in opts:
+ opts.append ('eps')
+
+ if 'eps' in opts and ('tex' in todo or
+ not os.path.isfile (basename + '.eps')):
+ todo.append ('eps')
+
+ if 'png' in opts and ('eps' in todo or
+ not os.path.isfile (basename + '.png')):
+ todo.append ('png')
+
+ if format == 'latex':
+ if 'eps' in opts :
+ newbody = newbody + get_output ('output-eps') % (basename, basename)
+ else:
+ newbody = newbody + get_output ('output-tex') % basename
+
+ elif format == 'texi':
+ newbody = newbody + get_output ('output-all') % (basename, basename)
+
+ return ('mudela', newbody, opts, todo, base)
+
+
+def find_eps_dims (match):
+ "Fill in dimensions of EPS files."
+
+ fn =match.group (1)
+ dims = bounding_box_dimensions (fn)
+
+ return '%ipt' % dims[0]
+
+
+def print_chunks (ch):
+ for c in ch:
+ print '-->%s\n%s' % (c[0], c[1])
+ if len (c) > 2:
+ print '==>%s' % list (c[2:])
+ print foo
+
+
+def transform_input_file (in_filename, out_filename):
+ """Read the input, and deliver a list of chunks
+ ready for writing.
+ """
+
+ chunks = read_doc_file (in_filename)
+
+ #. Process \mudela and \mudelafile.
+ for func in [find_mudela_shorthand_chunks,
+ find_mudela_chunks]:
+ newchunks = []
+ for c in chunks:
+ if c[0] == 'input':
+ newchunks = newchunks + func (c[1])
+ else:
+ newchunks.append (c)
+ chunks = newchunks
+
+ opts = []
+ if chunks:
+ opts = scan_preamble (chunks[0][1])
+
+ (chap,sect,count) = (0,0,0)
+ newchunks = []
+ # Count sections/chapters.
+ for c in chunks:
+ if c[0] == 'input':
+ (chap,sect,count) = advance_counters((chap,sect,count), opts, c[1])
+ elif c[0] == 'mudela':
+ base = '%s-%d.%d.%d' % (out_filename, chap, sect, count)
+ count = count + 1
+ c = schedule_mudela_block (base, c, opts)
+
+ newchunks.append (c)
+
+ chunks = newchunks
+ newchunks = []
+
+ # Do It.
+ if __main__.run_lilypond:
+ compile_all_files (chunks)
+
+ # finishing touch.
+ for c in chunks:
+ if c[0] == 'mudela' and 'eps' in c[2]:
+ body = re.sub (r"""\\mudelaepswidth{(.*?)}""", find_eps_dims, c[1])
+ newchunks.append (('mudela', body))
+ else:
+ newchunks.append (c)
+ chunks = newchunks
+
+ if chunks and chunks[0][0] == 'input':
+ chunks[0] = ('input', completize_preamble (chunks[0][1]))
+
+ return chunks
+
+def system (cmd):
+ sys.stderr.write ("invoking `%s'\n" % cmd)
+ st = os.system (cmd)
+ if st:
+ error ('Error command exited with value %d\n' % st)
+ return st
+
+def compile_all_files (chunks):
+ eps = []
+ tex = []
+ png = []
+ hash_dict = {}
+
+ for c in chunks:
+ if c[0] <> 'mudela':
+ continue
+ base = c[3][0]
+ exts = c[3][1:]
+ for e in exts:
+ if e == 'eps':
+ eps.append (base)
+ elif e == 'tex':
+ tex.append (base + '.ly')
+ elif e == 'png':
+ png.append (base)
+
+ if __main__.use_hash:
+ hash_dict[c[4]] = c[3][0]
+
+ if tex:
+ lilyopts = map (lambda x: '-I ' + x, include_path)
+ lilyopts = string.join (lilyopts, ' ' )
+ texfiles = string.join (tex, ' ')
+ system ('lilypond %s %s' % (lilyopts, texfiles))
+
+ for e in eps:
+ cmd = r"""tex %s; dvips -E -o %s %s""" % \
+ (e, e + '.eps', e)
+ system (cmd)
+
+ for g in png:
+ cmd = r"""gs -sDEVICE=pgm -dTextAlphaBits=4 -dGraphicsAlphaBits=4 -q -sOutputFile=- -r90 -dNOPAUSE %s -c quit | pnmcrop | pnmtopng > %s"""
+
+ cmd = cmd % (g + '.eps', g + '.png')
+ system (cmd)
+
+ if __main__.use_hash:
+ name = ''
+ last_name = ''
+ f = 0
+ ks = hash_dict.keys ()
+ ks.sort ()
+ for i in ks:
+ name = re.sub ("(.*)-[0-9]+\.[0-9]+\.[0-9]+", "\\1", i)
+ name = name + '.mix'
+ if name != last_name:
+ if last_name:
+ f.close ()
+ f = open (name, 'w')
+ last_name = name
+ f.write ("%s:%s\n" % (i, hash_dict[i]))
+
+
+def update_file (body, name):
+ same = 0
+ try:
+ f = open (name)
+ fs = f.read (-1)
+ same = (fs == body)
+ except:
+ pass
+
+ if not same:
+ f = open (name , 'w')
+ f.write (body)
+ f.close ()
+
+
+ return not same
+
+
+
+def getopt_args (opts):
+ "Construct arguments (LONG, SHORT) for getopt from list of options."
+ short = ''
+ long = []
+ for o in opts:
+ if o[1]:
+ short = short + o[1]
+ if o[0]:
+ short = short + ':'
+ if o[2]:
+ l = o[2]
+ if o[0]:
+ l = l + '='
+ long.append (l)
+ return (short, long)
+
+def option_help_str (o):
+ "Transform one option description (4-tuple ) into neatly formatted string"
+ sh = ' '
+ if o[1]:
+ sh = '-%s' % o[1]
+
+ sep = ' '
+ if o[1] and o[2]:
+ sep = ','
+
+ long = ''
+ if o[2]:
+ long= '--%s' % o[2]
+
+ arg = ''
+ if o[0]:
+ if o[2]:
+ arg = '='
+ arg = arg + o[0]
+ return ' ' + sh + sep + long + arg
+
+
+def options_help_str (opts):
+ "Convert a list of options into a neatly formatted string"
+ w = 0
+ strs =[]
+ helps = []
+ for o in opts:
+ s = option_help_str (o)
+ strs.append ((s, o[3]))
+ if len (s) > w:
+ w = len (s)
+
+ str = ''
+ for s in strs:
+ str = str + '%s%s%s\n' % (s[0], ' ' * (w - len(s[0]) + 3), s[1])
+ return str
+