#!/usr/local/bin/python3 import re import sys import os.path max_recurse_depth = 10 # limit depth of nested \Input statements re_comment = re.compile (r"^\s*%") re_file_name = re.compile (r"^\s*\\Input\{([_a-zA-Z0-9./-]+)\}") # use \Input to avoid confusion with \input def make_str (num,digits): return '{number:0{width}d}'.format(number=num,width=digits) def include_files (txt, file_name, recurse_depth): def grep (this_line, regex, the_group): result = regex.search (this_line) if result: found = True group = result.group (the_group) else: found = False group = "" return group, found def not_comment (the_line): return not re_comment.search (the_line) def read_include_name (the_line): file_name, found = grep (the_line,re_file_name,1) return file_name, found recurse_depth = recurse_depth + 1 if recurse_depth > max_recurse_depth: print ("> merge-tex.py: Recursion limit for \\Input{...} reached (max = "+str(max_recurse_depth)+"), exit") sys.exit(1) with open (file_name,'r') as src: for the_line in src: if not_comment (the_line): inc_file, found = read_include_name (the_line) if found: if not os.path.isfile (inc_file): print ("> merge-tex.py: Include file " + inc_file + " not found, exit.\n") sys.exit(1) if markup: txt.write (comment + " beg" + make_str(recurse_depth,2) + ": " + inc_file + "\n") recurse_depth = include_files (txt, inc_file, recurse_depth) txt.write (comment + " end" + make_str(recurse_depth,2) + ": " + inc_file + "\n") else: recurse_depth = include_files (txt, inc_file, recurse_depth) else: txt.write (the_line) else: txt.write (the_line) recurse_depth = recurse_depth - 1 return recurse_depth # ----------------------------------------------------------------------------- # the main code comment = "%%" # standard comment marker for LaTeX source import argparse parser = argparse.ArgumentParser(description="Merge a sequence of LaTeX files into a single LaTeX file") parser.add_argument("-i", dest="input", metavar="foo.tex", help="source file", required=True) parser.add_argument("-o", dest="output", metavar="bah.tex", help="output file", required=True) parser.add_argument("-S", dest="silent", default="False", action='store_true', help="suppress markup lines for each \\Input{foo.tex}", required=False) src_file_name = parser.parse_args().input out_file_name = parser.parse_args().output silent = parser.parse_args().silent if silent == "False": markup = True else: markup = False if src_file_name == out_file_name: print ("> merge-tex.py: Indentical files names for input and output, exit.") sys.exit (1) if not os.path.isfile (src_file_name): print ("> merge-tex.py: Source file " + src_file_name + " not found, exit.") sys.exit (1) with open (out_file_name,"w") as txt: recurse_depth = 0 if markup: txt.write (comment + " --------------------------------------------------------------\n") txt.write (comment + " Do not edit this file, it was created by merge-tex.py using:\n") txt.write (comment + " merge-tex.py -i " + src_file_name + " -o " + out_file_name + "\n") txt.write (comment + " --------------------------------------------------------------\n") txt.write (comment + " beg" + make_str(recurse_depth,2) + ": ./" + src_file_name + "\n") recurse_depth = include_files (txt, "./" + src_file_name, recurse_depth) txt.write (comment + " end" + make_str(recurse_depth,2) + ": ./" + src_file_name + "\n") else: recurse_depth = include_files (txt, "./" + src_file_name, recurse_depth) if not recurse_depth == 0: print("> merge-tex.py: error during merger") print("> recursion depth should be zero, actual value: "+str(recurse_depth))