]> git.donarmstrong.com Git - lilypond.git/blob - python/book_texinfo.py
Lilypond-book: Implement MusicXML support in lilypond-book
[lilypond.git] / python / book_texinfo.py
1 # -*- coding: utf-8 -*-
2
3 import re
4 import book_base as BookBase
5 from book_snippets import *
6
7 # Recognize special sequences in the input.
8 #
9 #   (?P<name>regex) -- Assign result of REGEX to NAME.
10 #   *? -- Match non-greedily.
11 #   (?!...) -- Match if `...' doesn't match next (without consuming
12 #              the string).
13 #
14 #   (?m) -- Multiline regex: Make ^ and $ match at each line.
15 #   (?s) -- Make the dot match all characters including newline.
16 #   (?x) -- Ignore whitespace in patterns.
17 # Possible keys are:
18 #     'multiline_comment', 'verbatim', 'lilypond_block', 'singleline_comment',
19 #     'lilypond_file', 'include', 'lilypond', 'lilypondversion'
20 TexInfo_snippet_res = {
21     'include': r'''(?mx)
22           ^(?P<match>
23           @include\s+
24            (?P<filename>\S+))''',
25
26     'lilypond': r'''(?smx)
27           ^[^\n]*?(?!@c\s+)[^\n]*?
28           (?P<match>
29           @lilypond\s*(
30           \[
31            \s*(?P<options>.*?)\s*
32           \])?\s*{
33            (?P<code>.*?)
34           })''',
35
36     'lilypond_block': r'''(?msx)
37           ^(?P<match>
38           @lilypond\s*(
39           \[
40            \s*(?P<options>.*?)\s*
41           \])?\s+?
42           ^(?P<code>.*?)
43           ^@end\s+lilypond)\s''',
44
45     'lilypond_file': r'''(?mx)
46           ^(?P<match>
47           @lilypondfile\s*(
48           \[
49            \s*(?P<options>.*?)\s*
50           \])?\s*{
51            (?P<filename>\S+)
52           })''',
53
54     'multiline_comment': r'''(?smx)
55           ^(?P<match>
56            (?P<code>
57            @ignore\s
58             .*?
59            @end\s+ignore))\s''',
60
61     'musicxml_file': r'''(?mx)
62           ^(?P<match>
63           @musicxmlfile\s*(
64           \[
65            \s*(?P<options>.*?)\s*
66           \])?\s*{
67            (?P<filename>\S+)
68           })''',
69
70     'singleline_comment': r'''(?mx)
71           ^.*
72           (?P<match>
73            (?P<code>
74            @c([ \t][^\n]*|)\n))''',
75
76     # Don't do this: It interferes with @code{@{}.
77     #        'verb': r'''(?P<code>@code{.*?})''',
78
79     'verbatim': r'''(?sx)
80           (?P<match>
81            (?P<code>
82            @example
83             \s.*?
84            @end\s+example\s))''',
85
86     'lilypondversion': r'''(?mx)
87          [^@](?P<match>
88           @lilypondversion)[^a-zA-Z]''',
89
90 }
91
92
93 TexInfo_output = {
94     ADDVERSION: r'''@example
95 \version @w{"@version{}"}
96 @end example
97 ''',
98
99     FILTER: r'''@lilypond[%(options)s]
100 %(code)s
101 @lilypond''',
102
103     OUTPUT: r'''
104 @iftex
105 @include %(base)s-systems.texi
106 @end iftex
107 ''',
108
109     OUTPUTIMAGE: r'''@noindent
110 @ifinfo
111 @image{%(info_image_path)s,,,%(alt)s,%(ext)s}
112 @end ifinfo
113 @html
114 <p>
115  <a href="%(base)s%(ext)s">
116   <img align="middle"
117        border="0"
118        src="%(image)s"
119        alt="%(alt)s">
120  </a>
121 </p>
122 @end html
123 ''',
124
125     PRINTFILENAME: '''
126 @html
127 <a href="%(base)s%(ext)s">
128 @end html
129 @file{%(filename)s}
130 @html
131 </a>
132 @end html
133     ''',
134
135     QUOTE: r'''@quotation
136 %(str)s@end quotation
137 ''',
138
139     NOQUOTE: r'''@format
140 %(str)s@end format
141 ''',
142
143     VERBATIM: r'''@exampleindent 0
144 %(version)s@verbatim
145 %(verb)s@end verbatim
146 ''',
147
148     VERSION: r'''%(program_version)s''',
149 }
150
151
152 texinfo_line_widths = {
153     '@afourpaper': '160\\mm',
154     '@afourwide': '6.5\\in',
155     '@afourlatex': '150\\mm',
156     '@smallbook': '5\\in',
157     '@letterpaper': '6\\in',
158 }
159
160
161
162 texinfo_lang_re = re.compile ('(?m)^@documentlanguage (.*?)( |$)')
163
164 class BookTexinfoOutputFormat (BookBase.BookOutputFormat):
165     def __init__ (self):
166         BookBase.BookOutputFormat.__init__ (self)
167         self.format = "texinfo"
168         self.default_extension = ".texi"
169         self.snippet_res = TexInfo_snippet_res
170         self.output = TexInfo_output
171         self.handled_extensions = ['.itely', '.tely', '.texi', '.texinfo']
172         self.snippet_option_separator = '\s*,\s*'
173
174     def can_handle_format (self, format):
175         return (BookBase.BookOutputFormat.can_handle_format (self, format) or
176                (format in ['texi-html', 'texi']))
177
178     def process_options (self, global_options):
179         self.process_options_pdfnotdefault (global_options)
180
181     def get_document_language (self, source):
182         m = texinfo_lang_re.search (source)
183         if m and not m.group (1).startswith ('en'):
184             return m.group (1)
185         else:
186             return ''
187
188     def get_line_width (self, source):
189         for regex in texinfo_line_widths:
190             # FIXME: @layout is usually not in
191             # chunk #0:
192             #
193             #  \input texinfo @c -*-texinfo-*-
194             #
195             # Bluntly search first K items of
196             # source.
197             # s = chunks[0].replacement_text ()
198             if re.search (regex, source[:1024]):
199                 return texinfo_line_widths[regex]
200         return None
201
202     def adjust_snippet_command (self, cmd):
203         if '--formats' not in cmd:
204             return cmd + ' --formats=png '
205         else:
206             return cmd
207
208     def output_info (self, basename, snippet):
209         str = ''
210         rep = snippet.get_replacements ();
211         for image in snippet.get_images ():
212             rep1 = copy.copy (rep)
213             (rep1['base'], rep1['ext']) = os.path.splitext (image)
214             rep1['image'] = image
215
216             # URG, makeinfo implicitly prepends dot to extension.
217             # Specifying no extension is most robust.
218             rep1['ext'] = ''
219             rep1['alt'] = snippet.option_dict[ALT]
220             rep1['info_image_path'] = os.path.join (self.global_options.info_images_dir, rep1['base'])
221             str += self.output[OUTPUTIMAGE] % rep1
222
223         rep['base'] = basename
224         str += self.output[OUTPUT] % rep
225         return str
226
227     def snippet_output (self, basename, snippet):
228         str = self.output_print_filename (basename, snippet)
229         base = basename
230         if DOCTITLE in snippet.option_dict:
231             doctitle = base + '.doctitle'
232             translated_doctitle = doctitle + self.document_language
233             if os.path.exists (translated_doctitle):
234                 str += '@lydoctitle %s\n\n' % open (translated_doctitle).read ()
235             elif os.path.exists (doctitle):
236                 str += '@lydoctitle %s\n\n' % open (doctitle).read ()
237         if TEXIDOC in snippet.option_dict:
238             texidoc = base + '.texidoc'
239             translated_texidoc = texidoc + self.document_language
240             if os.path.exists (translated_texidoc):
241                 str += '@include %(translated_texidoc)s\n\n' % vars ()
242             elif os.path.exists (texidoc):
243                 str += '@include %(texidoc)s\n\n' % vars ()
244
245         substr = ''
246         rep = snippet.get_replacements ();
247         if VERBATIM in snippet.option_dict:
248             rep['version'] = ''
249             if ADDVERSION in snippet.option_dict:
250                 rep['version'] = self.output[ADDVERSION]
251             rep['verb'] = snippet.verb_ly ()
252             substr = self.output[VERBATIM] % rep
253         substr += self.output_info (basename, snippet)
254         if LILYQUOTE in snippet.option_dict:
255             substr = self.output[QUOTE] % {'str': substr}
256         str += substr
257
258 #                str += ('@ifinfo\n' + self.output_info () + '\n@end ifinfo\n')
259 #                str += ('@tex\n' + self.output_latex () + '\n@end tex\n')
260 #                str += ('@html\n' + self.output_html () + '\n@end html\n')
261
262         if QUOTE in snippet.option_dict:
263             str = self.output[QUOTE] % {'str': str}
264
265         # need par after image
266         str += '\n'
267
268         return str
269
270     def required_files (self, snippet, base, full, required_files):
271         return self.required_files_png (snippet, base, full, required_files)
272
273
274
275 BookBase.register_format (BookTexinfoOutputFormat ());