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