lilypond-0.1.36
[lilypond.git] / bin / mf-to-table.py
blob08ded81adf8c3bffff10c4a9bf7c2cc78570ecf2
1 #!@PYTHON@
3 #
4 # mf-to-table.py -- convert spacing info in MF logs .ly and .tex
5 #
6 # source file of the GNU LilyPond music typesetter
7 #
8 # (c) 1997 Han-Wen Nienhuys <hanwen@stack.nl>
9 #
11 import getopt
12 from string import *
13 import regex
14 import regsub
15 import os
16 import sys
17 import time
19 begin_autometric_re = regex.compile('@{')
20 end_autometric_re = regex.compile('@}')
21 autometric_re = regex.compile('@{\(.*\)@}')
22 version = '0.4'
24 class File:
25 """silly wrapper for Python file object."""
26 def __init__(self,nm, mode='r'):
27 if nm:
28 self.file_ = open(nm, mode);
29 elif mode == 'w':
30 self.file_ = sys.stdout
31 else:
32 self.file_ = sys.stdin
34 self.eof_ = 0;
35 def readline(self):
36 l= self.file_.readline();
37 if not l:
38 self.eof_ = 1;
39 return l;
40 def write(self, str):
41 self.file_.write(str)
42 def eof(self):
43 return self.eof_
44 def close(self):
45 self.file_.close()
46 def __del__(self):
47 self.close();
49 class Feta_file(File):
50 """Read Feta metrics from a metafont log-file."""
51 def read_autometricline(self):
52 line = ''
53 while end_autometric_re.search(line) == -1 and not self.eof():
54 suf = File.readline(self)
55 if begin_autometric_re.search(line) == -1:
56 line = ''
57 line = line + regsub.sub('\n','', suf)
59 if self.eof():
60 return ''
62 return line;
63 def readline(self):
64 """return what is enclosed in one @{ @} pair"""
65 line = '';
66 while autometric_re.search(line) == -1 and not self.eof():
67 line = self.read_autometricline()
69 if self.eof():
70 return '';
72 return autometric_re.group(1);
73 def __init__(self, nm):
74 File.__init__(self, nm)
75 def do_file(infile_nm):
76 infile = readline();
79 # FIXME: should parse output for {} to do indenting.
81 class Indentable_file(File):
82 """Output file with support for indentation"""
83 def __init__(self,nm, mode):
84 File.__init__(self,nm,mode)
85 self.current_indent_ = 0
86 self.delta_indent_ = 4
87 def writeline (self, str):
88 File.write(self, str)
89 def writeeol(self):
90 File.write(self, '\n')
91 File.write(self, ' '* self.current_indent_)
93 def indent(self):
94 self.current_indent_ = self.delta_indent_ + self.current_indent_;
95 def dedent(self):
96 self.current_indent_ = self.current_indent_ - self.delta_indent_;
97 if self.current_indent_ < 0:
98 raise 'Nesting!'
100 def write(self, str):
101 lines = split(str, '\n')
102 for l in lines[:-1]:
103 self.writeline(l)
104 self.writeeol()
105 self.writeline (lines[-1])
107 class Ly_file(Indentable_file):
108 """extra provisions for mozarella quirks"""
109 def print_lit(self, str):
110 self.write('\"%s\"\t' % str)
112 def print_f_dimen(self, f):
113 self.write( '%.2f\\pt\t' % f);
115 def print_dimen(self, str):
116 self.print_f_dimen(atof(str))
118 def neg_print_dimen(self, str):
119 self.print_f_dimen(-atof(str));
121 def def_symbol(self, lily_id, tex_id, dims):
122 self.print_lit(lily_id)
123 self.print_lit('\\\\' + tex_id)
125 self.neg_print_dimen(dims [0])
126 self.print_dimen(dims [1])
127 self.neg_print_dimen(dims [2])
128 self.print_dimen(dims [3])
129 self.write('\n')
132 class Log_reader:
133 """Read logs, destill info, and put into output files"""
134 def output_label(self, line):
136 if not line:
137 return;
138 tags = split(line, '@:')
139 label = tags[0]
140 name = tags[1]
141 ly = self.lyfile
142 if tags[0] == 'font':
143 ly.indent()
144 ly.write("% name=\\symboltables {\n")
145 self.texfile.write("% name\n")
146 elif label == "group":
147 ly.indent()
148 ly.print_lit(name)
149 ly.write(' = \\table {\n')
150 self.texfile.write("% " + name + "\n")
151 elif label == "puorg":
152 ly.dedent()
153 ly.write("}\n")
154 self.texfile.write("\n")
155 elif label == "tnof":
156 ly.dedent()
157 ly.write("% } % $name\n")
158 elif label == "char":
159 code = tags[2]
160 id = tags [7]
161 texstr = tags [8]
163 ly.def_symbol(id, texstr, tags[3:7])
165 self.texfile.write("\\fetdef\\%s{%s}\n" % (texstr, code))
166 else:
167 raise 'unknown label: ' + label
170 def do_file(self,filenm):
171 self.lyfile.write('\n% input from ' + filenm + '\n')
172 self.texfile.write('\n% input from ' + filenm + '\n')
173 feta = Feta_file(filenm)
174 while not feta.eof():
175 line = feta.readline()
176 self.output_label(line)
177 feta.close()
179 def __init__(self, lyfile_nm, texfile_nm):
180 self.lyfile = Ly_file(lyfile_nm, 'w')
181 self.texfile = Indentable_file(texfile_nm, 'w')
184 headerstr = '%% Creator: %s\n%% Automatically generated on %s\n%% Do not edit' % \
185 (program_id(), today_str())
187 self.lyfile.write(headerstr)
188 self.texfile.write(headerstr)
190 def close(self):
191 self.lyfile.close()
192 self.texfile.close()
194 def __del__(self):
195 self.close()
197 def today_str():
198 return time.asctime(time.localtime(time.time()))
200 def program_id():
201 return 'mf-to-table.py version ' + version;
203 def identify():
204 sys.stdout.write(program_id() + '\n')
206 def help():
207 sys.stdout.write("Usage: mf-to-table [options] LOGFILEs\n"
208 + "Generate mozarella metrics table from preparated feta log\n\n"
209 + "Options:\n"
210 + " -h, --help print this help\n"
211 + " -l, --ly=FILE name output table\n"
212 + " -t, --tex=FILE name output tex chardefs\n")
215 def main():
216 identify()
217 (options, files) = getopt.getopt(
218 sys.argv[1:], 'hl:t:', ['ly=', 'tex=', 'debug', 'help'])
220 lyfile_nm = texfile_nm = '';
221 for opt in options:
222 o = opt[0]
223 a = opt[1]
224 if o == '--ly' or o == '-l':
225 lyfile_nm = a
226 elif o == '--tex' or o == '-t':
227 texfile_nm = a
228 elif o== '--help' or o == '-h':
229 help()
230 elif o == '--debug':
231 debug_b = 1
232 else:
233 raise getopt.error
235 log_reader = Log_reader(lyfile_nm, texfile_nm)
236 for filenm in files:
237 log_reader.do_file(filenm)
238 log_reader.close()
241 main()