# lys-to-tely.py # # This file is part of LilyPond, the GNU music typesetter. # # Copyright (C) 2001 Jan Nieuwenhuizen , # 2002-2020 Han-Wen Nienhuys # # LilyPond is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # LilyPond is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with LilyPond. If not, see . ''' TODO: * Add @nodes, split at sections? * -o --output listed in help is not implemented?! ''' import sys import os import getopt import re import glob program_name = 'lys-to-tely' include_snippets = '@lysnippets' fragment_options = 'printfilename,texidoc' help_text = r"""Usage: %(program_name)s [OPTIONS]... LY-FILE... Construct tely doc from LY-FILEs. Options: -h, --help print this help -f, --fragment-options=OPTIONS use OPTIONS as lilypond-book fragment options -o, --output=NAME write tely doc to NAME --prefix=PREFIX prefix filenames with PREFIX -i, --input-filenames=NAME read list of files from a file instead of stdin -g, --glob-input=GLOB a string which will be passed to glob.glob(GLOB) -t, --title=TITLE set tely doc title TITLE -a, --author=AUTHOR set tely author AUTHOR --template=TEMPLATE use TEMPLATE as Texinfo template file, instead of standard template; TEMPLATE should contain a command '%(include_snippets)s' to tell where to insert LY-FILEs. When this option is used, NAME and TITLE are ignored. """ def help(text): sys.stdout.write(text) sys.exit(0) (options, files) = getopt.getopt(sys.argv[1:], 'f:hn:t:', ['fragment-options=', 'help', 'name=', 'title=', 'author=', 'template=', 'input-filenames=', 'glob-input=', 'prefix=']) name = "ly-doc" title = "Ly Doc" author = "Han-Wen Nienhuys and Jan Nieuwenhuizen" input_filename = "" glob_input = "" template = r'''\input texinfo @c This file was autogenerated @c from: %s @c by: %s @setfilename %%(name)s.info @settitle %%(title)s @documentencoding UTF-8 @iftex @afourpaper @end iftex @finalout @c we do not want black boxes. @c fool ls-latex @ignore @author %%(author)s @title %%(title)s @end ignore @node Top, , , (dir) @top %%(title)s %s @bye ''' % (", ".join(files), sys.argv[0], include_snippets) prefix = '' for opt in options: o = opt[0] a = opt[1] if o == '-h' or o == '--help': # We can't use vars () inside a function, as that only contains all # local variables and none of the global variables! Thus we have to # generate the help text here and pass it to the function... help(help_text % vars()) elif o == '-n' or o == '--name': name = a elif o == '-t' or o == '--title': title = a elif o == '-a' or o == '--author': author = a elif o == '-i' or o == '--input-filenames': input_filename = a elif o == '-p' or o == '--glob-input': glob_input = a elif o == '-f' or o == '--fragment-options': fragment_options = a elif o == '--prefix': prefix = a elif o == '--template': template = open(a, 'r', encoding='utf8').read() else: raise Exception('unknown option: ' + o) html_file_re = re.compile(r'.*\.i?html?$') info_file_re = re.compile(r'.*\.info$') pdf_file_re = re.compile(r'.*\.i?pdf$') tex_file_re = re.compile(r'.*\.i?(la)?tex$') texi_file_re = re.compile(r'.*\.i?te(ly|xi|xinfo)$') xml_file_re = re.compile(r'.*\.i?(xm|mx)l$') def name2line(n): if texi_file_re.match(n): # We have a texi include file, simply include it: s = r"@include %s" % os.path.basename(n) elif (html_file_re.match(n) or info_file_re.match(n) or pdf_file_re.match(n) or tex_file_re.match(n)): s = r""" @ifhtml @html %s
@end html @end ifhtml """ % (os.path.basename(n), os.path.basename(n)) elif xml_file_re.match(n): # Assume it's a MusicXML file -> convert, create image etc. s = r""" @ifhtml @html @end html @end ifhtml @musicxmlfile[%s]{%s} """ % (os.path.basename(n), fragment_options, prefix + n) else: # Assume it's a lilypond file -> create image etc. s = r""" @ifhtml @html @end html @end ifhtml @lilypondfile[%s]{%s} """ % (os.path.basename(n), fragment_options, prefix + n) return s if glob_input: files = glob.glob(glob_input) elif input_filename: files = open(input_filename, encoding='utf8').read().split() if files: dir = os.path.dirname(name) or "." # don't strip .tely extension, Documentation/snippets uses .itely name = os.path.basename(name) template = template % vars() s = "\n".join(map(name2line, files)) s = template.replace(include_snippets, s, 1) f = "%s/%s" % (dir, name) h = open(f, "w", encoding="utf8") h.write(s) h.close() else: # not Unix philosophy, but hey, at least we notice when # we don't distribute any .ly files. sys.stderr.write( "No files specified. Doing nothing. Use -h to display usage.")