Fixes Issue 1504, allowing feather beam line breaking.
[lilypond/patrick.git] / python / book_texinfo.py
blob03f723754a43619cf055d82d9f89601ffeda3356
1 # -*- coding: utf-8 -*-
3 import re
4 import book_base as BookBase
5 from book_snippets import *
7 # Recognize special sequences in the input.
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).
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+))''',
26 'lilypond': r'''(?smx)
27 ^[^\n]*?(?!@c\s+)[^\n]*?
28 (?P<match>
29 @lilypond\s*(
31 \s*(?P<options>.*?)\s*
32 \])?\s*{
33 (?P<code>.*?)
34 })''',
36 'lilypond_block': r'''(?msx)
37 ^(?P<match>
38 @lilypond\s*(
40 \s*(?P<options>.*?)\s*
41 \])?\s+?
42 ^(?P<code>.*?)
43 ^@end\s+lilypond)\s''',
45 'lilypond_file': r'''(?mx)
46 ^(?P<match>
47 @lilypondfile\s*(
49 \s*(?P<options>.*?)\s*
50 \])?\s*{
51 (?P<filename>\S+)
52 })''',
54 'multiline_comment': r'''(?smx)
55 ^(?P<match>
56 (?P<code>
57 @ignore\s
58 .*?
59 @end\s+ignore))\s''',
61 'singleline_comment': r'''(?mx)
62 ^.*
63 (?P<match>
64 (?P<code>
65 @c([ \t][^\n]*|)\n))''',
67 # Don't do this: It interferes with @code{@{}.
68 # 'verb': r'''(?P<code>@code{.*?})''',
70 'verbatim': r'''(?sx)
71 (?P<match>
72 (?P<code>
73 @example
74 \s.*?
75 @end\s+example\s))''',
77 'lilypondversion': r'''(?mx)
78 [^@](?P<match>
79 @lilypondversion)[^a-zA-Z]''',
84 TexInfo_output = {
85 ADDVERSION: r'''@example
86 \version @w{"@version{}"}
87 @end example
88 ''',
90 FILTER: r'''@lilypond[%(options)s]
91 %(code)s
92 @lilypond''',
94 OUTPUT: r'''
95 @iftex
96 @include %(base)s-systems.texi
97 @end iftex
98 ''',
100 OUTPUTIMAGE: r'''@noindent
101 @ifinfo
102 @image{%(info_image_path)s,,,%(alt)s,%(ext)s}
103 @end ifinfo
104 @html
106 <a href="%(base)s.ly">
107 <img align="middle"
108 border="0"
109 src="%(image)s"
110 alt="%(alt)s">
111 </a>
112 </p>
113 @end html
114 ''',
116 PRINTFILENAME: '''
117 @html
118 <a href="%(base)s.ly">
119 @end html
120 @file{%(filename)s}
121 @html
122 </a>
123 @end html
124 ''',
126 QUOTE: r'''@quotation
127 %(str)s@end quotation
128 ''',
130 NOQUOTE: r'''@format
131 %(str)s@end format
132 ''',
134 VERBATIM: r'''@exampleindent 0
135 %(version)s@verbatim
136 %(verb)s@end verbatim
137 ''',
139 VERSION: r'''%(program_version)s''',
143 texinfo_line_widths = {
144 '@afourpaper': '160\\mm',
145 '@afourwide': '6.5\\in',
146 '@afourlatex': '150\\mm',
147 '@smallbook': '5\\in',
148 '@letterpaper': '6\\in',
153 texinfo_lang_re = re.compile ('(?m)^@documentlanguage (.*?)( |$)')
155 class BookTexinfoOutputFormat (BookBase.BookOutputFormat):
156 def __init__ (self):
157 BookBase.BookOutputFormat.__init__ (self)
158 self.format = "texinfo"
159 self.default_extension = ".texi"
160 self.snippet_res = TexInfo_snippet_res
161 self.output = TexInfo_output
162 self.handled_extensions = ['.itely', '.tely', '.texi', '.texinfo']
163 self.snippet_option_separator = '\s*,\s*'
165 def can_handle_format (self, format):
166 return (BookBase.BookOutputFormat.can_handle_format (self, format) or
167 (format in ['texi-html', 'texi']))
169 def process_options (self, global_options):
170 self.process_options_pdfnotdefault (global_options)
172 def get_document_language (self, source):
173 m = texinfo_lang_re.search (source)
174 if m and not m.group (1).startswith ('en'):
175 return m.group (1)
176 else:
177 return ''
179 def get_line_width (self, source):
180 for regex in texinfo_line_widths:
181 # FIXME: @layout is usually not in
182 # chunk #0:
184 # \input texinfo @c -*-texinfo-*-
186 # Bluntly search first K items of
187 # source.
188 # s = chunks[0].replacement_text ()
189 if re.search (regex, source[:1024]):
190 return texinfo_line_widths[regex]
191 return None
193 def adjust_snippet_command (self, cmd):
194 if '--formats' not in cmd:
195 return cmd + ' --formats=png '
196 else:
197 return cmd
199 def output_info (self, basename, snippet):
200 str = ''
201 rep = snippet.get_replacements ();
202 for image in snippet.get_images ():
203 rep1 = copy.copy (rep)
204 (rep1['base'], rep1['ext']) = os.path.splitext (image)
205 rep1['image'] = image
207 # URG, makeinfo implicitly prepends dot to extension.
208 # Specifying no extension is most robust.
209 rep1['ext'] = ''
210 rep1['alt'] = snippet.option_dict[ALT]
211 rep1['info_image_path'] = os.path.join (self.global_options.info_images_dir, rep1['base'])
212 str += self.output[OUTPUTIMAGE] % rep1
214 rep['base'] = basename
215 str += self.output[OUTPUT] % rep
216 return str
218 def snippet_output (self, basename, snippet):
219 str = self.output_print_filename (basename, snippet)
220 base = basename
221 if DOCTITLE in snippet.option_dict:
222 doctitle = base + '.doctitle'
223 translated_doctitle = doctitle + self.document_language
224 if os.path.exists (translated_doctitle):
225 str += '@lydoctitle %s\n\n' % open (translated_doctitle).read ()
226 elif os.path.exists (doctitle):
227 str += '@lydoctitle %s\n\n' % open (doctitle).read ()
228 if TEXIDOC in snippet.option_dict:
229 texidoc = base + '.texidoc'
230 translated_texidoc = texidoc + self.document_language
231 if os.path.exists (translated_texidoc):
232 str += '@include %(translated_texidoc)s\n\n' % vars ()
233 elif os.path.exists (texidoc):
234 str += '@include %(texidoc)s\n\n' % vars ()
236 substr = ''
237 rep = snippet.get_replacements ();
238 if VERBATIM in snippet.option_dict:
239 rep['version'] = ''
240 if ADDVERSION in snippet.option_dict:
241 rep['version'] = self.output[ADDVERSION]
242 rep['verb'] = snippet.verb_ly ()
243 substr = self.output[VERBATIM] % rep
244 substr += self.output_info (basename, snippet)
245 if LILYQUOTE in snippet.option_dict:
246 substr = self.output[QUOTE] % {'str': substr}
247 str += substr
249 # str += ('@ifinfo\n' + self.output_info () + '\n@end ifinfo\n')
250 # str += ('@tex\n' + self.output_latex () + '\n@end tex\n')
251 # str += ('@html\n' + self.output_html () + '\n@end html\n')
253 if QUOTE in snippet.option_dict:
254 str = self.output[QUOTE] % {'str': str}
256 # need par after image
257 str += '\n'
259 return str
261 def required_files (self, snippet, base, full, required_files):
262 return self.required_files_png (snippet, base, full, required_files)
266 BookBase.register_format (BookTexinfoOutputFormat ());