From 59e14ca1cb8dc807d3a015e7dbf36e2133d6d820 Mon Sep 17 00:00:00 2001 From: Karl Berry Date: Wed, 18 Sep 2013 23:01:10 +0000 Subject: lilyglyphs (18sep13) git-svn-id: svn://tug.org/texlive/trunk@31696 c570f23f-e606-0410-a88d-b1316a301751 --- .../scripts/lilyglyphs/lily-glyph-commands.py | 165 ++++++++++ .../scripts/lilyglyphs/lily-image-commands.py | 350 ++++++++++++++++++++ .../scripts/lilyglyphs/lily-rebuild-pdfs.py | 171 ++++++++++ .../scripts/lilyglyphs/lilyglyphs_common.py | 358 +++++++++++++++++++++ 4 files changed, 1044 insertions(+) create mode 100755 Master/texmf-dist/scripts/lilyglyphs/lily-glyph-commands.py create mode 100755 Master/texmf-dist/scripts/lilyglyphs/lily-image-commands.py create mode 100755 Master/texmf-dist/scripts/lilyglyphs/lily-rebuild-pdfs.py create mode 100755 Master/texmf-dist/scripts/lilyglyphs/lilyglyphs_common.py (limited to 'Master/texmf-dist/scripts') diff --git a/Master/texmf-dist/scripts/lilyglyphs/lily-glyph-commands.py b/Master/texmf-dist/scripts/lilyglyphs/lily-glyph-commands.py new file mode 100755 index 00000000000..ad6429338db --- /dev/null +++ b/Master/texmf-dist/scripts/lilyglyphs/lily-glyph-commands.py @@ -0,0 +1,165 @@ +#!/usr/bin/env python + +# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +# % +# This file is part of the 'lilyglyphs' LaTeX package. % +# ========== % +# % +# https://github.com/openlilylib/lilyglyphs % +# http://www.openlilylib.org/lilyglyphs % +# % +# Copyright 2012-2013 Urs Liska and others, ul@openlilylib.org % +# % +# 'lilyglyphs' is free software: you can redistribute it and/or modify % +# it under the terms of the LaTeX Project Public License, either % +# version 1.3 of this license or (at your option) any later version. % +# You may find the latest version of this license at % +# http://www.latex-project.org/lppl.txt % +# more information on % +# http://latex-project.org/lppl/ % +# and version 1.3 or later is part of all distributions of LaTeX % +# version 2005/12/01 or later. % +# % +# This work has the LPPL maintenance status 'maintained'. % +# The Current Maintainer of this work is Urs Liska (see above). % +# % +# This work consists of the files listed in the file 'manifest.txt' % +# which can be found in the 'license' directory. % +# % +# This program 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. % +# % +# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +# ######################################################################## +# # +# genGlyphCommands.py # +# # +# generate commands based on Emmentaler glyphs # +# # +# ######################################################################## + +import os, sys, argparse + +# import common library, depending on its location +scr_path, scr_name = os.path.split(sys.argv[0]) +if not 'lilyglyphs_common.py' in os.listdir(scr_path): + # the library is not in the same dir as the script + # first check if we're in a CTAN archive directory structure + libpath = os.path.normpath(os.path.join(scr_path, '..', 'lib')) + if 'lilyglyphs_common.py' in os.listdir(libpath): + # we're in a CTAN archive + sys.path.append(libpath) + else: + # we're not in a CTAN archive + # so we assume we're in a TeX installation. + import subprocess + try: + # use TeX's kpsewhich tool to locate the library file + # in the TeX installation + lib = subprocess.check_output(["kpsewhich", + "--progname=lilyglyphs", + "--format=texmfscripts", + "lilyglyphs_common.py"]) + except: + print '\nCommon library \"lilyglyphs_common.py\" not found.' + print 'Please refer to the manual for possible solutions.' + sys.exit(2) + # add the found path to Python's search path + sys.path.append(os.path.split(lib)[0]) + +import lilyglyphs_common as lg + +def main(input_file): + """Do the main work of the script""" + + in_dir, in_file = os.path.split(input_file) + os.chdir(in_dir) + + # load and parse input file + lg.read_input_file(in_file) + read_entries() + + # generate LaTeX commands and save them to output file + # (will be a .tex sibling of the input file) + lg.generate_latex_commands() + out_file, out_ext = os.path.splitext(input_file) + lg.write_latex_file(os.path.join(os.getcwd(), out_file + '.tex')) + +def read_entries(): + """Parse the input file and fill a dictionary""" + entry = {} + def reset_entry(): + """Set all members of the dict empty, + because not all are present in each entry.""" + entry['cmd'] = '' + entry['element'] = '' + entry['type'] = 'glyphname' + entry['comment'] = [] + entry['raise'] = '' + entry['scale'] = '' + + reset_entry() + scale = '' + rais = '' + for line in lg.definitions_file: + line = line.strip() + # empty line = end of entry + if not len(line): + # skip if cmd and glyph haven't been filled both + if not (entry['cmd'] and entry['element']): + print 'Skip malformed entry \'' + entry['cmd'] + '\'. Please check input file' + reset_entry() + else: + print 'Read entry \'' + entry['cmd'] + '\'' + lg.in_cmds[entry['cmd']] = {} + lg.in_cmds[entry['cmd']]['element'] = entry['element'] + lg.in_cmds[entry['cmd']]['type'] = entry['type'] + lg.in_cmds[entry['cmd']]['comment'] = entry['comment'] + if scale: + lg.in_cmds[entry['cmd']]['scale'] = scale + if rais: + lg.in_cmds[entry['cmd']]['raise'] = rais + reset_entry() + # ignore Python or LaTeX style comments + elif line[0] in '#%': + continue + else: + # add element to the entry + keyval = line.split('=') + if keyval[0] == 'scale': + scale = keyval[1] + elif keyval[0] == 'raise': + rais = keyval[1] + if keyval[0] == 'comment': + entry['comment'] = [keyval[1]] + else: + entry[keyval[0].strip()] = keyval[1].strip() + + +def usage(): + print 'genGlyphCommands.py' + print 'is part of the lilyglyphs package' + print '' + print 'Usage:' + print 'Pass the name (without path) of an input definitions file' + print '(this has to be located in the /stash_new_commands directory.' + print 'Please refer to the manual (documentation/lilyglyphs.pdf).' + +# #################################### +# Finally launch the program +if __name__ == "__main__": + # parse command line arguments + parser = argparse.ArgumentParser( + description='Generate LaTeX commands using Emmentaler glyphs', + parents=[lg.common_arguments]) + parser.add_argument('i', + type=lg.is_file, + metavar='INPUT', + help='File with command templates.') + args = parser.parse_args() + + # if we have exactly one existing file + # join its components and run the program + main(os.path.join(os.getcwd(), vars(args)['i'])) diff --git a/Master/texmf-dist/scripts/lilyglyphs/lily-image-commands.py b/Master/texmf-dist/scripts/lilyglyphs/lily-image-commands.py new file mode 100755 index 00000000000..4415876aa7b --- /dev/null +++ b/Master/texmf-dist/scripts/lilyglyphs/lily-image-commands.py @@ -0,0 +1,350 @@ +#!/usr/bin/env python + +# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +# % +# This file is part of the 'lilyglyphs' LaTeX package. % +# ========== % +# % +# https://github.com/openlilylib/lilyglyphs % +# http://www.openlilylib.org/lilyglyphs % +# % +# Copyright 2012-2013 Urs Liska and others, ul@openlilylib.org % +# % +# 'lilyglyphs' is free software: you can redistribute it and/or modify % +# it under the terms of the LaTeX Project Public License, either % +# version 1.3 of this license or (at your option) any later version. % +# You may find the latest version of this license at % +# http://www.latex-project.org/lppl.txt % +# more information on % +# http://latex-project.org/lppl/ % +# and version 1.3 or later is part of all distributions of LaTeX % +# version 2005/12/01 or later. % +# % +# This work has the LPPL maintenance status 'maintained'. % +# The Current Maintainer of this work is Urs Liska (see above). % +# % +# This work consists of the files listed in the file 'manifest.txt' % +# which can be found in the 'license' directory. % +# % +# This program 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. % +# % +# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +import os, sys, getopt, datetime, subprocess, argparse + +# import common library, depending on its location +scr_path, scr_name = os.path.split(sys.argv[0]) +if not 'lilyglyphs_common.py' in os.listdir(scr_path): + # the library is not in the same dir as the script + # first check if we're in a CTAN archive directory structure + libpath = os.path.normpath(os.path.join(scr_path, '..', 'lib')) + if 'lilyglyphs_common.py' in os.listdir(libpath): + # we're in a CTAN archive + sys.path.append(libpath) + else: + # we're not in a CTAN archive + # so we assume we're in a TeX installation. + import subprocess + try: + # use TeX's kpsewhich tool to locate the library file + # in the TeX installation + lib = subprocess.check_output(["kpsewhich", + "--progname=lilyglyphs", + "--format=texmfscripts", + "lilyglyphs_common.py"]) + except: + print '\nCommon library \"lilyglyphs_common.py\" not found.' + print 'Please refer to the manual for possible solutions.' + sys.exit(2) + # add the found path to Python's search path + sys.path.append(os.path.split(lib)[0]) + +import lilyglyphs_common as lg + + + +# ############### +# string to be printed before the actual command +lily_src_prefix = """\\version "2.16.2" + +#(set-global-staff-size 14) + +\paper { + indent = 0 +} +\header { + tagline = "" +} + +""" + +# string to be printed after the actual command definition +lily_src_score = """ + \\score { + \\new Staff \\with { + \\remove "Staff_symbol_engraver" + \\remove "Clef_engraver" + \\remove "Time_signature_engraver" + } +""" + +def main(): + """Do the actual work of the script""" + print '' + print 'buildglyphimages.py,' + print 'Part of lilyglyphs.' + print '' + + # set CWD and ensure the necessary subdirs are present + check_paths() + print '' + + # load and parse input file + lg.read_input_file(in_file) + read_entries() + print '' + + # generate LilyPond source files for each command + # and compile them + write_lily_src_files() + print '' + lg.compile_lily_files() + print '' + + # remove intermediate files and move pdfs to pdf directory + lg.cleanup_lily_files() + print '' + + # generate latex commands and example code + # and write them to the output file + lg.generate_latex_commands() + print '' + write_latex_file() + + +def check_paths(): + """Sets CWD to 'glyphimages' subdir or root of lilyglyphs_private + and makes sure that the necessary subdirectories are present""" + + # one level above 'definitions' is 'glyphimages' + os.chdir(os.path.join(in_path, '..')) + + # check the presence of the necessary subdirectories + # and create them if necessary + # (otherwise we'll get errors when trying to write in them) + ls = os.listdir('.') + if not lg.dir_lysrc in ls: + os.mkdir(lg.dir_lysrc) + if not lg.dir_pdfs in ls: + os.mkdir(lg.dir_pdfs) + if not lg.dir_cmd in ls: + os.mkdir(lg.dir_cmd) + +def cmd_filename(cmd_name): + if cmd_name.startswith('lily'): + return cmd_name[:4] + '-' + cmd_name[4:] + elif cmd_name.startswith('lily-'): + return cmd_name + else: + return 'lily-' + cmd_name + +# set default scale and raise arguments to empty +scale = '' +rais = '' + +def read_entries(): + """Parses the input source file and extracts glyph entries""" + print 'Read entries of LilyPond commands:' + for i in range(len(lg.definitions_file)): + if '%%lilyglyphs' in lg.definitions_file[i]: + i = read_entry(i) + print lg.lily_files + +def read_entry(i): + """Reads a single glyph entry from the input file and stores it + in the global dictionary lg.in_cmds""" + global scale, rais + # read comment line(s) + i += 1 + is_protected = False + comment = [] + # loop over the comment line(s) + while i < len(lg.definitions_file): + line = lg.definitions_file[i].strip() + # check for 'protected' entries that shouldn't be processed newly + if not line[0] == '%': + break + elif '%%protected' in line: + is_protected = True + elif 'scale=' in line: + dummy, scale = line.split('=') + elif 'raise=' in line: + dummy, rais = line.split('=') + else: + line = line[1:].strip() + comment.append(line) + i += 1 + + # remove any empty lines + while len(lg.definitions_file[i].strip()) == 0: + i += 1 + + # read command name + line = lg.definitions_file[i].strip() + cmd_name = line[: line.find('=') - 1] + print '- ' + cmd_name, + if is_protected: + print '(protected and skipped)' + else: + print '' #(for line break only) + + # read actual command until we find a line the begins with a closing curly bracket + i += 1 + lilySrc = [] + while lg.definitions_file[i][0] != '}': + lilySrc.append(lg.definitions_file[i]) + i += 1 + if not is_protected: + lg.in_cmds[cmd_name] = {} + lg.in_cmds[cmd_name]['comment'] = comment + lg.in_cmds[cmd_name]['lilySrc'] = lilySrc + lg.in_cmds[cmd_name]['element'] = cmd_filename(cmd_name) + lg.in_cmds[cmd_name]['type'] = 'image' + if scale: + lg.in_cmds[cmd_name]['scale'] = scale + if rais: + lg.in_cmds[cmd_name]['raise'] = rais + + lg.lily_files.append(cmd_filename(cmd_name)) + return i + + +def usage(): + print """buildglyphimages. Part of the lilyglyphs package. + Parses a template file, creates + single .ly files from it, uses LilyPond to create single glyph + pdf files and set up template files to be used in LaTeX. + The input file has to be located in the glyphimages folder + of either the lilyglyph package itself or of a copy of + the lilyglyphs_private directory structure contained in the + distribution. + For detailed instructions refer to the manual. + Usage: + buildglyphimages.py in-file-name. + """ + +def write_file_info(name, fout): + """Formats file specific information for the lilyPond source file""" + long_line = '% This file defines a single glyph to be created with LilyPond: %\n' + width = len(long_line) - 1 + header = '%' * width + '\n' + spacer = '%' + ' ' * (width - 2) + '%\n' + padding = width - len(name) - 8 + fout.write(header) + fout.write(spacer) + fout.write(long_line) + fout.write(spacer) + fout.write('% ' + name + '.ly' + ' ' * padding + '%\n') + fout.write(spacer) + fout.write(header) + fout.write(lg.signature()) + fout.write('\n\n') + +def write_latex_file(): + """Composes LaTeX file and writes it to disk""" + print 'Generate LaTeX file' + print lg.dir_cmd, in_basename + lg.write_latex_file(os.path.join(os.getcwd(), lg.dir_cmd, in_basename + '.tex')) + +def write_lily_src_files(): + """Generates one .ly file for each found new command""" + skip_cmds = [] + print 'Write .ly files for each entry:' + for cmd_name in lg.in_cmds: + print '- ' + cmd_name + gen_src_name = os.path.join(lg.dir_lysrc, cmd_filename(cmd_name) + '.ly') + # handle existing commands + if os.path.exists(gen_src_name): + action = '' + while not (action == 'Y' or action == 'N'): + action = raw_input('already present. Overwrite (y/n)? ') + action = action.upper() + if action == 'N': + skip_cmds.append(cmd_name) + continue + + # open a single lily src file for write access + fout = open(gen_src_name, 'w') + + #output the license information + fout.write(lg.lilyglyphs_copyright_string) + fout.write('\n') + + #output information on the actual file + write_file_info(cmd_name, fout) + + #write the default LilyPond stuff + fout.write(lily_src_prefix) + + # write the comment for the command + fout.write('%{\n') + for line in lg.in_cmds[cmd_name]['comment']: + fout.write(line + '\n') + fout.write('%}\n\n') + + # write the actual command + fout.write(cmd_name + ' = {\n') + for line in lg.in_cmds[cmd_name]['lilySrc']: + fout.write(line + '\n') + fout.write('}\n') + + # write the score definition + fout.write(lily_src_score) + + # finish the LilyPond file + fout.write(' \\' + cmd_name + '\n') + fout.write('}\n\n') + + fout.close() + + # remove skipped commands from in_cmds + print skip_cmds + for cmd_name in skip_cmds: + del lg.in_cmds[cmd_name] + lg.lily_files.remove(cmd_filename(cmd_name)) + +# #################################### +# Finally launch the program +if __name__ == "__main__": + + # parse command line arguments + parser = argparse.ArgumentParser( + description='Process templates to LilyPond input files,' + + 'compile these and generate LaTeX commands.', + parents=[lg.common_arguments]) + parser.add_argument('i', + type=lg.is_file, + metavar='INPUT', + help='File with command templates.') + args = parser.parse_args() + + # if we have exactly one existing file + # join its components and run the program + + # process filename argument, providing absolute path + script_path, script_name = os.path.split(sys.argv[0]) + + in_file = os.path.join(os.getcwd(), vars(args)['i']) + # check if the input file is in the right place + # this has to be the definitions subdir of + # the package directory or the lilyglyphs_private dir + in_path, in_filename = os.path.split(in_file) + in_path = os.path.normpath(in_path) + if not (('lilyglyphs' in in_path) and (in_path.endswith('definitions'))): + print 'File in the wrong location: ' + in_path + usage() + sys.exit(2) + in_basename, in_ext = os.path.splitext(in_filename) + main() diff --git a/Master/texmf-dist/scripts/lilyglyphs/lily-rebuild-pdfs.py b/Master/texmf-dist/scripts/lilyglyphs/lily-rebuild-pdfs.py new file mode 100755 index 00000000000..77dedfaaffe --- /dev/null +++ b/Master/texmf-dist/scripts/lilyglyphs/lily-rebuild-pdfs.py @@ -0,0 +1,171 @@ +#!/usr/bin/env python + +# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +# % +# This file is part of the 'lilyglyphs' LaTeX package. % +# ========== % +# % +# https://github.com/openlilylib/lilyglyphs % +# http://www.openlilylib.org/lilyglyphs % +# % +# Copyright 2012-2013 Urs Liska and others, ul@openlilylib.org % +# % +# 'lilyglyphs' is free software: you can redistribute it and/or modify % +# it under the terms of the LaTeX Project Public License, either % +# version 1.3 of this license or (at your option) any later version. % +# You may find the latest version of this license at % +# http://www.latex-project.org/lppl.txt % +# more information on % +# http://latex-project.org/lppl/ % +# and version 1.3 or later is part of all distributions of LaTeX % +# version 2005/12/01 or later. % +# % +# This work has the LPPL maintenance status 'maintained'. % +# The Current Maintainer of this work is Urs Liska (see above). % +# % +# This work consists of the files listed in the file 'manifest.txt' % +# which can be found in the 'license' directory. % +# % +# This program 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. % +# % +# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +# ######################################################################## +# # +# rebuild-pdfs.py # +# # +# This program looks in the directories where the generated .ly files # +# and the generated pdf images are stored. # +# If it finds that there are missing pdfs it will recompile them # +# using LilyPond. # +# # +# The main purpose is to allow the creation of pdf images of glyphs # +# that already have been processed to LaTeX commands but whose PDF # +# files have been lost. # +# The other purpose is to update the set of PDF files to a new version # +# of Emmentaler or LilyPond without touching the definitions. # +# # +# ######################################################################## + +import os, sys, subprocess, argparse + +# import common library, depending on its location +scr_path, scr_name = os.path.split(sys.argv[0]) +if not 'lilyglyphs_common.py' in os.listdir(scr_path): + # the library is not in the same dir as the script + # first check if we're in a CTAN archive directory structure + libpath = os.path.normpath(os.path.join(scr_path, '..', 'lib')) + if 'lilyglyphs_common.py' in os.listdir(libpath): + # we're in a CTAN archive + sys.path.append(libpath) + else: + # we're not in a CTAN archive + # so we assume we're in a TeX installation. + import subprocess + try: + # use TeX's kpsewhich tool to locate the library file + # in the TeX installation + lib = subprocess.check_output(["kpsewhich", + "--progname=lilyglyphs", + "--format=texmfscripts", + "lilyglyphs_common.py"]) + except: + print '\nCommon library \"lilyglyphs_common.py\" not found.' + print 'Please refer to the manual for possible solutions.' + sys.exit(2) + # add the found path to Python's search path + sys.path.append(os.path.split(lib)[0]) + +import lilyglyphs_common as lg + + +def main(): + """Main walk through the program""" + print 'rebuild-pdfs.py' + print 'regenerate all pdf images that are not present (anymore)' + print '' + + # Check if we are in a legal CWD and ensure a PDF subdir is present + check_paths() + + # build a list of commands with missing PDF files + src_files = check_missing_pdfs() + + # is there anything to be done at all? + if len(src_files) == 0: + print '' + print 'No image files missing, nothing to be done.' + print 'If you want to re-create pdfs, then delete them first' + sys.exit(0) + print '' + print 'Found ' + str(len(src_files)) + ' missing file(s).' + for cmd in src_files: + print '- ' + cmd + + # compile all LilyPond files without matching pdf + lg.lily_files = src_files + lg.compile_lily_files() + + # clean up directories + lg.cleanup_lily_files() + +def check_missing_pdfs(): + """Compares the list of LilyPond source and resulting PDF files. + Returns a list of LilyPond source file basenames + which don't have a corresponding PDF file""" + print 'Reading file lists, counting missing pdf files' + + # read existing .pdf files in lg.dir_pdfs + img_files = [] + for entry in os.listdir(lg.dir_pdfs): + entry = os.path.join(lg.dir_pdfs, entry) + if os.path.isfile(entry): + path, name = os.path.split(entry) + basename, ext = os.path.splitext(name) + if ext == '.pdf': + img_files.append(basename) + + # read existing .ly source files in in_dir + # and add them to the sources list if the image is missing + src_files = [] + for entry in os.listdir(lg.dir_lysrc): + entry = os.path.join(lg.dir_lysrc, entry) + if os.path.isfile(entry): + path, name = os.path.split(entry) + basename, ext = os.path.splitext(name) + if ext == '.ly' and basename not in img_files: + src_files.append(basename) + return src_files + +def check_paths(): + """Checks if we're in the right CWD + and makes sure that there is a pdf output directory available""" + + print 'Checking directories ...' + + # check the presence of the necessary subdirectories + ls = os.listdir('.') + if not 'generated_src' in ls: + print 'No LilyPond source files directory found.' + print 'Sorry, there is something wrong :-(' + print 'Current working directory is: ' + os.getcwd() + print 'Please consult the manual.' + sys.exit(2) + if not 'pdfs' in ls: + os.mkdir('pdfs') + + print '... done' + print '' + + +# #################################### +# Finally launch the program +if __name__ == "__main__": + # parse command line arguments + parser = argparse.ArgumentParser( + description='Rebuild all pdfs missing in the \'pdfs\' subdiredtory', + parents=[lg.common_arguments]) + args = parser.parse_args() + main() diff --git a/Master/texmf-dist/scripts/lilyglyphs/lilyglyphs_common.py b/Master/texmf-dist/scripts/lilyglyphs/lilyglyphs_common.py new file mode 100755 index 00000000000..5e988065d62 --- /dev/null +++ b/Master/texmf-dist/scripts/lilyglyphs/lilyglyphs_common.py @@ -0,0 +1,358 @@ +#!/usr/bin/env python + +# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +# % +# This file is part of the 'lilyglyphs' LaTeX package. % +# ========== % +# % +# https://github.com/openlilylib/lilyglyphs % +# http://www.openlilylib.org/lilyglyphs % +# % +# Copyright 2012-2013 Urs Liska and others, ul@openlilylib.org % +# % +# 'lilyglyphs' is free software: you can redistribute it and/or modify % +# it under the terms of the LaTeX Project Public License, either % +# version 1.3 of this license or (at your option) any later version. % +# You may find the latest version of this license at % +# http://www.latex-project.org/lppl.txt % +# more information on % +# http://latex-project.org/lppl/ % +# and version 1.3 or later is part of all distributions of LaTeX % +# version 2005/12/01 or later. % +# % +# This work has the LPPL maintenance status 'maintained'. % +# The Current Maintainer of this work is Urs Liska (see above). % +# % +# This work consists of the files listed in the file 'manifest.txt' % +# which can be found in the 'license' directory. % +# % +# This program 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. % +# % +# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +# ######################################################################## +# # +# lilyglyphs_common.py # +# # +# Common functionality for the Python scripts in lilyglyphs # +# # +# ######################################################################## + +import os, sys, datetime, subprocess, argparse + +# ################ +# Global variables + +definitions_file = [] +version_string = '0.2.1' + +# ###################### +# Common CL arguments +common_arguments = argparse.ArgumentParser(add_help=False) +common_arguments.add_argument('-v', '--version', + action='version', + version='%(prog)s ' + version_string) + +def is_file(filename): + if os.path.exists(filename): + return filename + else: + msg = "file %s not found" % filename + raise argparse.ArgumentTypeError(msg) + + +# ########### +# Directories +dir_defs = 'definitions' +dir_lysrc = 'generated_src' +dir_pdfs = 'pdfs' +dir_cmd = 'generated_cmd' + +# LilyPond commands +in_cmds = {} +# LilyPond source files (corresponds to in_cmds) +# stores basenames without path and extension +lily_files = [] +# LaTeX commands +latex_cmds = {} + +# ####### +# Strings + +lilyglyphs_copyright_string = """ +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% % +% This file is part of the 'lilyglyphs' LaTeX package. % +% ========== % +% % +% https://github.com/openlilylib/lilyglyphs % +% http://www.openlilylib.org/lilyglyphs % +% % +% Copyright 2012-2013 Urs Liska and others, ul@openlilylib.org % +% % +% 'lilyglyphs' is free software: you can redistribute it and/or modify % +% it under the terms of the LaTeX Project Public License, either % +% version 1.3 of this license or (at your option) any later version. % +% You may find the latest version of this license at % +% http://www.latex-project.org/lppl.txt % +% more information on % +% http://latex-project.org/lppl/ % +% and version 1.3 or later is part of all distributions of LaTeX % +% version 2005/12/01 or later. % +% % +% This work has the LPPL maintenance status 'maintained'. % +% The Current Maintainer of this work is Urs Liska (see above). % +% % +% This work consists of the files listed in the file 'manifest.txt' % +% which can be found in the 'license' directory. % +% % +% This program 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. % +% % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +""" + +latexfile_start_comment = """ +% This file contains definitions for the new commands +% along with test code for them. +% You can test the commands in the context of continuous text +% and adjust their design time options. +% Afterwards you should manually move the commands to +% the appropriate .inp files, +% because this file will be overwritten by the next run +% of SCRIPT_NAME! +% If you want to keep this file for reference +% you should save it with a new name. +% +% There also is a table containing entries for use in the lilyglyph manual. +% You can either copy the whole table to the appropriate +% place in lilyglyphs.tex or just copy individual table rows. + +\\documentclass{scrartcl} +\\usepackage{lilyglyphsStyle} + +%%%%%%%%%%%%%%%%%%%%%%%%% +% new command definitions + +""" + +latexfile_begin_document = """ + +\\begin{document} + +%%%%%%%%%%%%% +% Text output + +\\section*{New \\lilyglyphs{} commands} +""" + +latexfile_reftable = """ +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Reference table to be used in the manual +% (use complete or single lines) + +\\begin{reftable}{New commands}{newcommands} +""" + +latexfile_testcode = """\\end{reftable} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Test code for fine-tuning the new commands +""" + +# ############## +# Code templates + +# template string to build the test code for the commands +# 'CMD' will be replaced by the actual command_name +testcode_template = """ + +\\noindent\\textbf{\\textsf{Continuous text for} \\cmd{CMD}:}\\\\ +Lorem ipsum dolor sit amet, consectetur adipisicing elit, +sed \\CMD{} do eiusmod tempor incididunt ut labore et dolore magna aliqua \\CMD.\\\\ +\\CMD{} Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip +ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse +cillum dolore eu fugiat nulla pariatur \\CMD. +\\CMD{} Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. + +\\bigskip +""" + +# Default values for optional argument in generated commands +DEF_SCALE = '1' +DEF_RAISE = '0' + +# template strings to build the command from +# 'CMD' will be replaced by the actual command_name +# 'ELEM' will be replaced by the actual content element to be rendered + +cmd_templates = {} +cmd_templates['image'] = """\\newcommand*{\\CMD}[1][]{% + \\setkeys{lilyDesignOptions}{scale=SCALE,raise=RAISE}% + \\lilyPrintImage[#1]{ELEM}% +} + +""" + +cmd_templates['glyphname'] = """\\newcommand*{\\CMD}[1][]{% + \\setkeys{lilyDesignOptions}{scale=SCALE,raise=RAISE}% + \\lilyPrint[#1]{\\lilyGetGlyph{ELEM}}% +} + +""" + +cmd_templates['number'] = """\\newcommand*{\\CMD}[1][]{% + \\setkeys{lilyDesignOptions}{scale=SCALE,raise=RAISE}% + \\lilyPrint[#1]{\\lilyGetGlyphByNumber{ELEM}}% +} + +""" + +cmd_templates['dynamics'] = """\\newcommand{\\CMD}[1][]{% + \\mbox{% + \\lilyDynamics[#1]{ELEM}% + }% +} + +""" + +cmd_templates['text'] = """\\newcommand{\\CMD}[1][]{% + \\setkeys{lilyDesignOptions}{scale=SCALE,raise=RAISE}% + \\mbox{% + \\lilyText[#1]{ELEM}% + }% +} + +""" + +def cleanup_lily_files(): + """Removes unneccessary files from LilyPond compilation, + rename and remove the preview PDF files to the right directory.""" + + print 'Clean up directories' + + # iterate through dir_lysrc + os.chdir(dir_lysrc) + for entry in os.listdir('.'): + if os.path.isfile(entry): + name, extension = os.path.splitext(entry) + #remove unnecessary files + if not extension in ['.pdf', '.ly']: + os.remove(entry) + if extension == '.pdf': + # remove full-page pdf + if '.preview' in name: + newfile = entry.replace('.preview.', '.') + newfile = os.path.join('..', dir_pdfs, newfile) + # rename/move small 'preview' pdf + os.rename(entry, newfile) + else: + os.remove(entry) + os.chdir('..') + +def compile_lily_files(): + """Compiles LilyPond files to """ + print 'Compile with LilyPond:' + for file in lily_files: + args = [] + args.append("lilypond") + args.append("-o") + args.append(dir_lysrc) + args.append("-dpreview") + args.append("-dno-point-and-click") + args.append(os.path.join(dir_lysrc, file + ".ly")) + subprocess.call(args) + print '' + +def generate_latex_commands(): + """Generates the templates for the commands in a new LaTeX file. + These should manually be moved to the appropriate .inp files + in lilyglyphs""" + + # iterate over the list of commands + for cmd_name in in_cmds: + latex_cmds[cmd_name] = {} + + # create LaTeX command + cmd = [] + for line in in_cmds[cmd_name]['comment']: + cmd.append('% ' + line + '\n') + cmd.append(signature() + '\n') + template = cmd_templates[in_cmds[cmd_name]['type']] + template = template.replace('CMD', cmd_name) + if 'scale' in in_cmds[cmd_name]: + scale = in_cmds[cmd_name]['scale'] + else: + scale = DEF_SCALE + template = template.replace('SCALE', scale) + if 'raise' in in_cmds[cmd_name]: + rais = in_cmds[cmd_name]['raise'] + else: + rais = DEF_RAISE + template = template.replace('RAISE', rais) + cmd.append(template.replace('ELEM', in_cmds[cmd_name]['element'])) + latex_cmds[cmd_name]['cmd'] = cmd + + # create LaTeX test code + tc = [] + tc.append(testcode_template.replace('CMD', cmd_name)) + latex_cmds[cmd_name]['testcode'] = tc + +def read_input_file(in_file): + """Reads the input source file and stores it + in the global variable definitions_file""" + global definitions_file + + print 'Read input file ' + in_file + + # check for existence of input file + if not os.path.exists(in_file): + print 'File ' + in_file + ' not found.' + print 'Please specify an input file' + sys.exit(2) + + fin = open(in_file, 'r') + for line in fin: + definitions_file.append(line.rstrip(' \n')) + fin.close() + +def script_name(): + dummy, result = os.path.split(sys.argv[0]) + return result + +def signature(): + """Returns a signature to be inserted in an output file""" + return '% created by ' + script_name() + ' on ' + str(datetime.date.today()) + +def write_latex_file(file_name): + fout = open(file_name, 'w') + fout.write('% New Glyphs for the lilyglyphs package\n') + fout.write(signature() + '\n') + fout.write(latexfile_start_comment.replace('SCRIPT_NAME', script_name())) + + # write out command definitions + sorted_cmds = sorted(latex_cmds.iterkeys()) + for cmd_name in sorted_cmds: + for line in latex_cmds[cmd_name]['cmd']: + fout.write(line) + + fout.write(latexfile_begin_document) + fout.write(signature()[2:]+ '\n') + fout.write(latexfile_reftable) + + # write out the reference table + row_template = '\\CMD & \\cmd{CMD} & description\\\\' + for cmd_name in sorted_cmds: + fout.write(row_template.replace('CMD', cmd_name) + '\n') + fout.write(latexfile_testcode) + + # write out the test code + for cmd_name in sorted_cmds: + for line in latex_cmds[cmd_name]['testcode']: + fout.write(line) + + fout.write('\\end{document}\n') + fout.close() -- cgit v1.2.3