1 # -*- coding: utf-8 -*-
8 import book_base as BookBase
9 from book_snippets import *
13 progress = ly.progress
16 debug = ly.debug_output
18 # Recognize special sequences in the input.
20 # (?P<name>regex) -- Assign result of REGEX to NAME.
21 # *? -- Match non-greedily.
22 # (?!...) -- Match if `...' doesn't match next (without consuming
25 # (?m) -- Multiline regex: Make ^ and $ match at each line.
26 # (?s) -- Make the dot match all characters including newline.
27 # (?x) -- Ignore whitespace in patterns.
29 # 'multiline_comment', 'verbatim', 'lilypond_block', 'singleline_comment',
30 # 'lilypond_file', 'include', 'lilypond', 'lilypondversion'
46 \s*(?P<options>.*?)\s*
55 \\begin\s*(?P<env>{lilypond}\s*)?(
57 \s*(?P<options>.*?)\s*
58 \])?(?(env)|\s*{lilypond})
61 \\end\s*{lilypond})''',
69 \s*(?P<options>.*?)\s*
80 \s*(?P<options>.*?)\s*
108 \\end\s*{verbatim}))''',
113 \\lilypondversion)[^a-zA-Z]''',
117 FILTER: r'''\begin{lilypond}[%(options)s]
124 \ifx\preLilyPondExample \undefined
126 \expandafter\preLilyPondExample
128 \def\lilypondbook{}%%
129 \input{%(base)s-systems.tex}
130 \ifx\postLilyPondExample \undefined
132 \expandafter\postLilyPondExample
136 PRINTFILENAME: r'''\texttt{%(filename)s}
140 QUOTE: r'''\begin{quote}
144 VERBATIM: r'''\noindent
145 \begin{verbatim}%(verb)s\end{verbatim}
148 VERSION: r'''%(program_version)s''',
156 # Retrieve dimensions from LaTeX
157 LATEX_INSPECTION_DOCUMENT = r'''
161 \typeout{textwidth=\the\textwidth}
162 \typeout{columnsep=\the\columnsep}
163 \makeatletter\if@twocolumn\typeout{columns=2}\fi\makeatother
167 # Do we need anything else besides `textwidth'?
168 def get_latex_textwidth (source, global_options):
172 m = re.search (r'''(?P<preamble>\\begin\s*{document})''', source)
174 warning (_ ("cannot find \\begin{document} in LaTeX document"))
177 preamble = source[:m.start (0)]
178 latex_document = LATEX_INSPECTION_DOCUMENT % {'preamble': preamble}
180 (handle, tmpfile) = tempfile.mkstemp('.tex')
181 tmpfileroot = os.path.splitext (tmpfile)[0]
182 tmpfileroot = os.path.split (tmpfileroot)[1]
183 auxfile = tmpfileroot + '.aux'
184 logfile = tmpfileroot + '.log'
186 tmp_handle = os.fdopen (handle,'w')
187 tmp_handle.write (latex_document)
190 progress (_ ("Running `%s' on file `%s' to detect default page settings.\n")
191 % (global_options.latex_program, tmpfile))
192 cmd = '%s %s' % (global_options.latex_program, tmpfile)
193 debug ("Executing: %s\n" % cmd)
194 run_env = os.environ.copy()
195 run_env['LC_ALL'] = 'C'
196 run_env['TEXINPUTS'] = '%s:%s' % \
197 (global_options.input_dir, run_env.get('TEXINPUTS',""))
199 ### unknown why this is necessary
200 universal_newlines = True
201 if sys.platform == 'mingw32':
202 universal_newlines = False
203 ### use os.system to avoid weird sleep() problems on
204 ### GUB's python 2.4.2 on mingw
205 # make file to write to
206 output_dir = tempfile.mkdtemp()
207 output_filename = os.path.join(output_dir, 'output.txt')
209 cmd += " > %s" % output_filename
210 oldtexinputs = os.environ.get ('TEXINPUTS')
211 os.environ['TEXINPUTS'] = run_env['TEXINPUTS']
212 returncode = os.system(cmd)
214 os.environ['TEXINPUTS'] = oldtexinputs
216 del os.environ['TEXINPUTS']
217 parameter_string = open(output_filename).read()
219 warning (_ ("Unable to auto-detect default settings:\n"))
221 os.remove(output_filename)
224 proc = subprocess.Popen (cmd,
226 universal_newlines=universal_newlines,
228 stdout=subprocess.PIPE, stderr=subprocess.PIPE)
229 (parameter_string, error_string) = proc.communicate ()
230 if proc.returncode != 0:
231 warning (_ ("Unable to auto-detect default settings:\n%s")
234 if os.path.exists (auxfile):
236 if os.path.exists (logfile):
237 parameter_string = file (logfile).read()
241 m = re.search ('columns=([0-9.]+)', parameter_string)
243 columns = int (m.group (1))
246 m = re.search ('columnsep=([0-9.]+)pt', parameter_string)
248 columnsep = float (m.group (1))
250 m = re.search ('textwidth=([0-9.]+)pt', parameter_string)
252 textwidth = float (m.group (1))
254 warning (_ ("cannot detect textwidth from LaTeX"))
257 debug ('Detected values:')
258 debug (' columns = %s' % columns)
259 debug (' columnsep = %s' % columnsep)
260 debug (' textwidth = %s' % textwidth)
263 textwidth = (textwidth - columnsep) / columns
264 debug ('Adjusted value:')
265 debug (' textwidth = %s' % textwidth)
270 def modify_preamble (chunk):
271 str = chunk.replacement_text ()
272 if (re.search (r"\\begin *{document}", str)
273 and not re.search ("{graphic[sx]", str)):
274 str = re.sub (r"\\begin{document}",
275 r"\\usepackage{graphics}" + '\n'
276 + r"\\begin{document}",
278 chunk.override_text = str
285 class BookLatexOutputFormat (BookBase.BookOutputFormat):
287 BookBase.BookOutputFormat.__init__ (self)
288 self.format = "latex"
289 self.default_extension = ".tex"
290 self.snippet_res = Latex_snippet_res
291 self.output = Latex_output
292 self.handled_extensions = ['.latex', '.lytex', '.tex']
293 self.image_formats = "ps"
294 self.snippet_option_separator = '\s*,\s*'
296 def process_options (self, global_options):
297 self.process_options_pdfnotdefault (global_options)
299 def get_line_width (self, source):
300 textwidth = get_latex_textwidth (source, self.global_options)
301 return '%.0f\\pt' % textwidth
303 def input_fullname (self, input_filename):
304 # Use kpsewhich if available, otherwise fall back to the default:
305 if ly.search_exe_path ('kpsewhich'):
306 trial = os.popen ('kpsewhich ' + input_filename).read()[:-1]
309 return BookBase.BookOutputFormat.input_fullname (self, input_filename)
311 def process_chunks (self, chunks):
313 if (c.is_plain () and
314 re.search (r"\\begin *{document}", c.replacement_text())):
319 def snippet_output (self, basename, snippet):
321 rep = snippet.get_replacements ();
322 rep['base'] = basename.replace ('\\', '/')
323 rep['filename'] = os.path.basename (snippet.filename).replace ('\\', '/')
324 rep['ext'] = snippet.ext
325 if PRINTFILENAME in snippet.option_dict:
326 str += self.output[PRINTFILENAME] % rep
327 if VERBATIM in snippet.option_dict:
328 rep['verb'] = snippet.verb_ly ()
329 str += self.output[VERBATIM] % rep
331 str += self.output[OUTPUT] % rep
333 ## todo: maintain breaks
335 breaks = snippet.ly ().count ("\n")
336 str += "".ljust (breaks, "\n").replace ("\n","%\n")
338 if QUOTE in snippet.option_dict:
339 str = self.output[QUOTE] % {'str': str}
345 BookBase.register_format (BookLatexOutputFormat ());