]> git.donarmstrong.com Git - lilypond.git/blob - bin/mf-to-table.py
08ded81adf8c3bffff10c4a9bf7c2cc78570ecf2
[lilypond.git] / bin / mf-to-table.py
1 #!@PYTHON@
2
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
10
11 import getopt
12 from string import *
13 import regex
14 import regsub
15 import os
16 import sys
17 import time
18
19 begin_autometric_re = regex.compile('@{')
20 end_autometric_re = regex.compile('@}')
21 autometric_re = regex.compile('@{\(.*\)@}')
22 version = '0.4'
23
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
33             
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();
48
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)
58
59         if self.eof():
60            return ''
61
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()
68
69         if self.eof():
70             return '';
71
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();
77
78 #
79 # FIXME: should parse output for {} to do indenting.
80 #
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_)
92
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!'
99
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])
106
107 class Ly_file(Indentable_file):
108     """extra provisions for mozarella quirks"""
109     def print_lit(self, str):
110         self.write('\"%s\"\t' % str)
111
112     def print_f_dimen(self, f):
113         self.write( '%.2f\\pt\t' % f);
114
115     def print_dimen(self, str):
116         self.print_f_dimen(atof(str))
117     
118     def neg_print_dimen(self, str):
119         self.print_f_dimen(-atof(str));
120         
121     def def_symbol(self, lily_id, tex_id, dims):
122         self.print_lit(lily_id)
123         self.print_lit('\\\\' + tex_id)
124
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')
130         
131         
132 class Log_reader:
133     """Read logs, destill info, and put into output files"""
134     def output_label(self, line):
135
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]
162             
163             ly.def_symbol(id, texstr, tags[3:7])
164             
165             self.texfile.write("\\fetdef\\%s{%s}\n" % (texstr, code))
166         else:
167             raise 'unknown label: ' + label
168
169
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()
178
179     def __init__(self, lyfile_nm, texfile_nm):      
180         self.lyfile = Ly_file(lyfile_nm, 'w')
181         self.texfile = Indentable_file(texfile_nm, 'w')
182
183
184         headerstr = '%% Creator: %s\n%% Automatically generated on %s\n%% Do not edit' % \
185                    (program_id(), today_str())
186
187         self.lyfile.write(headerstr)
188         self.texfile.write(headerstr)
189
190     def close(self):
191         self.lyfile.close()
192         self.texfile.close()
193
194     def __del__(self):
195         self.close()
196
197 def today_str():
198     return time.asctime(time.localtime(time.time()))
199         
200 def program_id():
201     return 'mf-to-table.py version ' + version;
202
203 def identify():
204     sys.stdout.write(program_id() + '\n')
205     
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")
213
214
215 def main():
216     identify()
217     (options, files) = getopt.getopt(
218         sys.argv[1:], 'hl:t:', ['ly=', 'tex=', 'debug', 'help'])
219
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
234
235     log_reader = Log_reader(lyfile_nm, texfile_nm)
236     for filenm in files:
237         log_reader.do_file(filenm)
238     log_reader.close()
239
240
241 main()