]> git.donarmstrong.com Git - lilypond.git/blobdiff - scripts/lilypond-book.py
* scripts/lilypond-book.py (compose_ly): bugfix for relative < 0.
[lilypond.git] / scripts / lilypond-book.py
index 8849394a7cd1d028a053f43d68932ed9b98eadc5..7d298fd518ec1a431a1c9746a6ab97ea3dd172f7 100644 (file)
@@ -159,8 +159,8 @@ snippet_res = {
        'lilypond' : '(?m)^(?P<match>@lilypond(\[(?P<options>[^]]*)\])?{(?P<code>.*?)})',
        'lilypond_block': r'''(?ms)^(?P<match>@lilypond(\[(?P<options>[^]]*)\])?\s(?P<code>.*?)@end lilypond)\s''',
        'lilypond_file': '(?m)^(?P<match>@lilypondfile(\[(?P<options>[^]]*)\])?{(?P<filename>[^}]+)})',
-       'multiline_comment': r"(?sm)^\s*(?!@c\s+)(?P<code>@ignore\s.*?@end ignore)\s",
-       'singleline_comment': r"(?m)^.*(?P<match>(?P<code>@c([ \t][^\n]*|)\n))",
+       'multiline_comment': r'(?sm)^\s*(?!@c\s+)(?P<code>@ignore\s.*?@end\s+ignore)\s',
+       'singleline_comment': r'(?m)^.*(?P<match>(?P<code>@c([ \t][^\n]*|)\n))',
 
 # don't do this: fucks up with @code{@{}
 #      'verb': r'''(?P<code>@code{.*?})''',
@@ -195,7 +195,7 @@ ly_options = {
        'noindent' : r'''
     indent = 0.0\mm''',
        'notime' : r'''
-    \translator {
+    \context {
         \StaffContext
         \remove Time_signature_engraver
     }''',
@@ -219,12 +219,12 @@ output = {
   <a href="%(base)s.ly">''',
        OUTPUT: r'''
     <img align="center" valign="center"
-         border="0" src="%(picture)s" alt="[picture of music]">''',
+         border="0" src="%(image)s" alt="[image of music]">''',
        PRINTFILENAME:'<p><tt><a href="%(base)s.ly">%(filename)s</a></tt></p>',
        VERBATIM: r'''<pre>
 %(verb)s</pre>''',
        },
-       
+
        LATEX : {
        AFTER: '',
        BEFORE: '',
@@ -242,19 +242,20 @@ output = {
 %(verb)s\end{verbatim}
 ''',
        },
-       
-       TEXINFO :       {
+
+       TEXINFO : {
        AFTER: '',
        BEFORE: '',
+       OUTPUT: r'''
+       @image{%(base)s,,,[image of music],%(ext)s}
+''',   
        PRINTFILENAME: '''@file{%(filename)s}
 
        ''',
        VERBATIM: r'''@example
 %(verb)s@end example
 ''',
-       
        },
-       
        }
 
 PREAMBLE_LY = r'''%% Generated by %(program_name)s
@@ -270,11 +271,13 @@ FRAGMENT_LY = r'''\score{
 }'''
 FULL_LY = '%(code)s'
 
-texi_linewidths = { 'afourpaper': '160 \\mm',
-                   'afourwide': '6.5\\in',
-                   'afourlatex': '150 \\mm',
-                   'smallbook': '5 \\in' ,
-                   'letterpaper': '6\\in'}
+texinfo_linewidths = {
+       '@afourpaper': '160 \\mm',
+       '@afourwide': '6.5 \\in',
+       '@afourlatex': '150 \\mm',
+       '@smallbook': '5 \\in' ,
+       '@letterpaper': '6\\in',
+       }
 
 def classic_lilypond_book_compatibility (o):
        if o == 'singleline':
@@ -311,7 +314,7 @@ def compose_ly (code, options):
                body = FULL_LY
 
        # defaults
-       relative = 0
+       relative = 1
        staffsize = 16
        override = {}
        override.update (default_ly_options)
@@ -350,7 +353,14 @@ def compose_ly (code, options):
        if RELATIVE in override.keys () and override[RELATIVE]:
                relative = string.atoi (override[RELATIVE])
 
-       relative_quotes = (",,,", ",,", ",", "", "'", "''", "'''")[relative+4]
+       relative_quotes = ''
+
+       # 1 = central C
+       if relative < 0:
+               relative_quotes += ',' * (- relative)
+       elif relative > 0:
+               relative_quotes += "'" * relative
+               
        program_name = __main__.program_name
        paper_string = string.join (paper_options, '\n    ') % override
        preamble_string = string.join (preamble_options, '\n    ') % override
@@ -476,8 +486,12 @@ class Lilypond_snippet (Snippet):
 
        def is_outdated (self):
                base = self.basename ()
+               ## FIXME: adding PNG to is_outdated test fixes
+               ##        interrupted (web) builds.
+               ##        should only do this if PNG is actually target
                if os.path.exists (base + '.ly') \
                   and os.path.exists (base + '.tex') \
+                  and os.path.exists (base + '.png') \
                   and (use_hash_p \
                        or self.ly () == open (base + '.ly').read ()):
                        # TODO: something smart with target formats
@@ -489,36 +503,52 @@ class Lilypond_snippet (Snippet):
                func = Lilypond_snippet.__dict__ ['output_' + self.format]
                return func (self)
        
-       def output_html (self):
+       def get_images (self):
                base = self.basename ()
-               str = ''
-               if format == HTML:
-                       str = self.output_print_filename (HTML)
-                       if VERBATIM in self.options:
-                               verb = verbatim_html (self.substring ('code'))
-                               str += write (output[HTML][VERBATIM] % vars ())
-                               
                # URGUGHUGHUGUGHU
                single = '%(base)s.png' % vars ()
                multiple = '%(base)s-page1.png' % vars ()
-               pictures = (single,)
+               images = (single,)
                if os.path.exists (multiple) \
                   and (not os.path.exists (single)\
                        or (os.stat (multiple)[stat.ST_MTIME] \
                            > os.stat (single)[stat.ST_MTIME])):
-                       pictures = glob.glob ('%(base)s-page*.png' % vars ())
+                       images = glob.glob ('%(base)s-page*.png' % vars ())
+               return images
                
+       def output_html (self):
+               str = ''
+               base = self.basename ()
+               if format == HTML:
+                       str += self.output_print_filename (HTML)
+                       if VERBATIM in self.options:
+                               verb = verbatim_html (self.substring ('code'))
+                               str += write (output[HTML][VERBATIM] % vars ())
+
                str += output[HTML][BEFORE] % vars ()
-               for picture in pictures:
+               for image in self.get_images ():
+                       base, ext = os.path.splitext (image)
                        str += output[HTML][OUTPUT] % vars ()
                str += output[HTML][AFTER] % vars ()
                return str
-                       
+
+       def output_info (self):
+               str = self.output_print_filename (HTML)
+               str = output[TEXINFO][BEFORE] % vars ()
+               for image in self.get_images ():
+                       base, ext = os.path.splitext (image)
+                       # URG, makeinfo implicitely prepends dot to ext
+                       # specifying no extension is most robust
+                       ext = ''
+                       str += output[TEXINFO][OUTPUT] % vars ()
+               str += output[TEXINFO][AFTER] % vars ()
+               return str
+
        def output_latex (self):
                str = ''
                base = self.basename ()
                if format == LATEX:
-                       str = self.output_print_filename (LATEX)
+                       str += self.output_print_filename (LATEX)
                        if  VERBATIM in self.options:
                                verb = self.substring ('code')
                                str += (output[LATEX][VERBATIM] % vars ())
@@ -537,6 +567,11 @@ class Lilypond_snippet (Snippet):
 
        def output_texinfo (self):
                str = ''
+               # self.output_print_filename (TEXINFO)
+               str += ('@html\n' + self.output_print_filename (HTML)
+                       + '\n@end html\n')
+               str += ('@tex\n' + self.output_print_filename (LATEX)
+                       + '\n@end tex\n')
                base = self.basename ()
                if TEXIDOC in self.options:
                        texidoc = base + '.texidoc'
@@ -547,9 +582,10 @@ class Lilypond_snippet (Snippet):
                        verb = verbatim_texinfo (self.substring ('code'))
                        str +=  (output[TEXINFO][VERBATIM] % vars ())
 
+               str += ('@ifinfo\n' + self.output_info () + '\n@end ifinfo\n')
                str += ('@tex\n' + self.output_latex () + '\n@end tex\n')
                str += ('@html\n' + self.output_html () + '\n@end html\n')
-               # need par after picture
+               # need par after image
                str += '\n'
 
                return str
@@ -589,7 +625,7 @@ def find_toplevel_snippets (s, types):
                                 m = res[type].search (s[index:endex])
                                if not m:
                                        continue
-                               
+
                                cl = Snippet
                                if snippet_type_to_class.has_key (type):
                                        cl = snippet_type_to_class[type]
@@ -600,6 +636,17 @@ def find_toplevel_snippets (s, types):
                         if found[type] \
                           and (not first or found[type][0] < found[first][0]):
                                 first = type
+
+                               # FIXME.
+
+                               # Limiting the search space is a cute
+                               # idea, but this *requires* to search
+                               # for possible containing blocks
+                               # first, at least long as we do not
+                               # search for the start of blocks, but
+                               # always/directly for the entire
+                               # @block ... @end block.
+                               
                                 endex = found[first][0]
 
                 if not first:
@@ -609,6 +656,7 @@ def find_toplevel_snippets (s, types):
                (start , snip) = found[first]
                snippets.append (Substring (s, index, start))
                snippets.append (snip)
+               found[first] = None
                 index = start + len (snip.match.group (0))
 
         return snippets
@@ -754,6 +802,14 @@ def do_file (input_filename):
                        output_filename = (output_name
                                           + '/' + input_base
                                           + format2ext[format])
+
+
+               if (os.path.exists (input_filename) and 
+                   os.path.exists (output_filename) and 
+                   os.path.samefile (output_filename, input_fullname)):
+                       ly.error (_("Output would overwrite input file; use --output."))
+                       sys.exit (2)
+
                output_file = open (output_filename, 'w')
                if output_name:
                        os.chdir (output_name)
@@ -761,13 +817,14 @@ def do_file (input_filename):
        ly.progress (_ ("Reading %s...") % input_fullname)
        source = in_handle.read ()
        ly.progress ('\n')
-       
+
+       # FIXME: containing blocks must be first, see find_toplevel_snippets
        snippet_types = (
+               'multiline_comment',
+               'verbatim',
                'lilypond_block',
 #              'verb',
-               'verbatim',
                'singleline_comment',
-               'multiline_comment',
                'lilypond_file',
                'include',
                'lilypond', )
@@ -783,9 +840,12 @@ def do_file (input_filename):
                        default_ly_options[LINEWIDTH] = '''%.0f\\pt''' \
                                                        % textwidth
                elif format == TEXINFO:
-                       for (k, v) in texi_linewidths.items ():
-                               s = chunks[0].replacement_text ()
-                               if re.search (k, s):
+                       for (k, v) in texinfo_linewidths.items ():
+                               # FIXME: @paper is usually not in chunk #0:
+                               #        \input texinfo @c -*-texinfo-*-
+                               # bluntly search first K of source
+                               # s = chunks[0].replacement_text ()
+                               if re.search (k, source[:1024]):
                                        default_ly_options[LINEWIDTH] = v
                                        break