]> git.donarmstrong.com Git - lilypond.git/blobdiff - python/book_latex.py
Imported Upstream version 2.14.2
[lilypond.git] / python / book_latex.py
diff --git a/python/book_latex.py b/python/book_latex.py
new file mode 100644 (file)
index 0000000..677e88a
--- /dev/null
@@ -0,0 +1,270 @@
+# -*- coding: utf-8 -*-
+
+import re
+import tempfile
+import os
+import book_base as BookBase
+from book_snippets import *
+import lilylib as ly
+global _;_=ly._
+
+progress = ly.progress
+warning = ly.warning
+error = ly.error
+
+# Recognize special sequences in the input.
+#
+#   (?P<name>regex) -- Assign result of REGEX to NAME.
+#   *? -- Match non-greedily.
+#   (?!...) -- Match if `...' doesn't match next (without consuming
+#              the string).
+#
+#   (?m) -- Multiline regex: Make ^ and $ match at each line.
+#   (?s) -- Make the dot match all characters including newline.
+#   (?x) -- Ignore whitespace in patterns.
+# Possible keys are:
+#     'multiline_comment', 'verbatim', 'lilypond_block', 'singleline_comment',
+#     'lilypond_file', 'include', 'lilypond', 'lilypondversion'
+Latex_snippet_res = {
+    'include':
+         r'''(?smx)
+          ^[^%\n]*?
+          (?P<match>
+          \\input\s*{
+           (?P<filename>\S+?)
+          })''',
+
+    'lilypond':
+         r'''(?smx)
+          ^[^%\n]*?
+          (?P<match>
+          \\lilypond\s*(
+          \[
+           \s*(?P<options>.*?)\s*
+          \])?\s*{
+           (?P<code>.*?)
+          })''',
+
+    'lilypond_block':
+         r'''(?smx)
+          ^[^%\n]*?
+          (?P<match>
+          \\begin\s*(?P<env>{lilypond}\s*)?(
+          \[
+           \s*(?P<options>.*?)\s*
+          \])?(?(env)|\s*{lilypond})
+           (?P<code>.*?)
+          ^[^%\n]*?
+          \\end\s*{lilypond})''',
+
+    'lilypond_file':
+         r'''(?smx)
+          ^[^%\n]*?
+          (?P<match>
+          \\lilypondfile\s*(
+          \[
+           \s*(?P<options>.*?)\s*
+          \])?\s*\{
+           (?P<filename>\S+?)
+          })''',
+
+    'singleline_comment':
+         r'''(?mx)
+          ^.*?
+          (?P<match>
+           (?P<code>
+           %.*$\n+))''',
+
+    'verb':
+         r'''(?mx)
+          ^[^%\n]*?
+          (?P<match>
+           (?P<code>
+           \\verb(?P<del>.)
+            .*?
+           (?P=del)))''',
+
+    'verbatim':
+         r'''(?msx)
+          ^[^%\n]*?
+          (?P<match>
+           (?P<code>
+           \\begin\s*{verbatim}
+            .*?
+           \\end\s*{verbatim}))''',
+
+    'lilypondversion':
+         r'''(?smx)
+          (?P<match>
+          \\lilypondversion)[^a-zA-Z]''',
+}
+
+Latex_output = {
+    FILTER: r'''\begin{lilypond}[%(options)s]
+%(code)s
+\end{lilypond}''',
+
+    OUTPUT: r'''{%%
+\parindent 0pt
+\noindent
+\ifx\preLilyPondExample \undefined
+\else
+  \expandafter\preLilyPondExample
+\fi
+\def\lilypondbook{}%%
+\input %(base)s-systems.tex
+\ifx\postLilyPondExample \undefined
+\else
+  \expandafter\postLilyPondExample
+\fi
+}''',
+
+    PRINTFILENAME: '''\\texttt{%(filename)s}
+''',
+
+    QUOTE: r'''\begin{quotation}
+%(str)s
+\end{quotation}''',
+
+    VERBATIM: r'''\noindent
+\begin{verbatim}%(verb)s\end{verbatim}
+''',
+
+    VERSION: r'''%(program_version)s''',
+}
+
+
+
+
+
+###
+# Retrieve dimensions from LaTeX
+LATEX_INSPECTION_DOCUMENT = r'''
+\nonstopmode
+%(preamble)s
+\begin{document}
+\typeout{textwidth=\the\textwidth}
+\typeout{columnsep=\the\columnsep}
+\makeatletter\if@twocolumn\typeout{columns=2}\fi\makeatother
+\end{document}
+'''
+
+# Do we need anything else besides `textwidth'?
+def get_latex_textwidth (source, global_options):
+    m = re.search (r'''(?P<preamble>\\begin\s*{document})''', source)
+    if m == None:
+        warning (_ ("cannot find \\begin{document} in LaTeX document"))
+
+        ## what's a sensible default?
+        return 550.0
+
+    preamble = source[:m.start (0)]
+    latex_document = LATEX_INSPECTION_DOCUMENT % {'preamble': preamble}
+
+    (handle, tmpfile) = tempfile.mkstemp('.tex')
+    logfile = os.path.splitext (tmpfile)[0] + '.log'
+    logfile = os.path.split (logfile)[1]
+
+    tmp_handle = os.fdopen (handle,'w')
+    tmp_handle.write (latex_document)
+    tmp_handle.close ()
+
+    ly.system ('%s %s' % (global_options.latex_program, tmpfile),
+               be_verbose=global_options.verbose)
+    parameter_string = file (logfile).read()
+
+    os.unlink (tmpfile)
+    os.unlink (logfile)
+
+    columns = 0
+    m = re.search ('columns=([0-9.]+)', parameter_string)
+    if m:
+        columns = int (m.group (1))
+
+    columnsep = 0
+    m = re.search ('columnsep=([0-9.]+)pt', parameter_string)
+    if m:
+        columnsep = float (m.group (1))
+
+    textwidth = 0
+    m = re.search ('textwidth=([0-9.]+)pt', parameter_string)
+    if m:
+        textwidth = float (m.group (1))
+        if columns:
+            textwidth = (textwidth - columnsep) / columns
+
+    return textwidth
+
+
+def modify_preamble (chunk):
+    str = chunk.replacement_text ()
+    if (re.search (r"\\begin *{document}", str)
+      and not re.search ("{graphic[sx]", str)):
+        str = re.sub (r"\\begin{document}",
+               r"\\usepackage{graphics}" + '\n'
+               + r"\\begin{document}",
+               str)
+        chunk.override_text = str
+
+
+
+
+
+
+class BookLatexOutputFormat (BookBase.BookOutputFormat):
+    def __init__ (self):
+        BookBase.BookOutputFormat.__init__ (self)
+        self.format = "latex"
+        self.default_extension = ".tex"
+        self.snippet_res = Latex_snippet_res
+        self.output = Latex_output
+        self.handled_extensions = ['.latex', '.lytex', '.tex']
+        self.image_formats = "ps"
+        self.snippet_option_separator = '\s*,\s*'
+
+    def process_options (self, global_options):
+        self.process_options_pdfnotdefault (global_options)
+
+    def get_line_width (self, source):
+        textwidth = get_latex_textwidth (source, self.global_options)
+        return '%.0f\\pt' % textwidth
+
+    def input_fullname (self, input_filename):
+        # Use kpsewhich if available, otherwise fall back to the default:
+        if ly.search_exe_path ('kpsewhich'):
+            return os.popen ('kpsewhich ' + input_filename).read()[:-1]
+        else:
+            return BookBase.BookOutputFormat.input_fullname (self, input_filename)
+
+    def process_chunks (self, chunks):
+        for c in chunks:
+            if (c.is_plain () and
+              re.search (r"\\begin *{document}", c.replacement_text())):
+                modify_preamble (c)
+                break
+        return chunks
+
+    def snippet_output (self, basename, snippet):
+        str = ''
+        rep = snippet.get_replacements ();
+        rep['base'] = basename
+        str += self.output_print_filename (basename, snippet)
+        if VERBATIM in snippet.option_dict:
+            rep['verb'] = snippet.verb_ly ()
+            str += self.output[VERBATIM] % rep
+
+        str += self.output[OUTPUT] % rep
+
+        ## todo: maintain breaks
+        if 0:
+            breaks = snippet.ly ().count ("\n")
+            str += "".ljust (breaks, "\n").replace ("\n","%\n")
+
+        if QUOTE in snippet.option_dict:
+            str = self.output[QUOTE] % {'str': str}
+        return str
+
+
+
+
+BookBase.register_format (BookLatexOutputFormat ());