From b5733b97894ecbafab7b6cdb25a61aa56b6f1f14 Mon Sep 17 00:00:00 2001 From: Robert Managan Date: Sat, 15 Sep 2012 22:29:47 -0700 Subject: Support auxiliary files created by \newglossary command --- src/CHANGES.txt | 4 ++ src/engine/SCons/Tool/tex.py | 56 +++++++++++++-- test/TEX/newglossary.py | 158 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 214 insertions(+), 4 deletions(-) create mode 100644 test/TEX/newglossary.py diff --git a/src/CHANGES.txt b/src/CHANGES.txt index 51eb505..048068f 100644 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -18,6 +18,10 @@ RELEASE 2.X.X - From Gary Oberbrunner: - Fix MSVS solution generation for VS11, and fixed tests. + From Rob Managan: + - Updated the TeX builder to support the \newglossary command + in LaTeX's glossaries package and the files it creates. + RELEASE 2.2.0 - Mon, 05 Aug 2012 15:37:48 +0000 From dubcanada on Bitbucket: diff --git a/src/engine/SCons/Tool/tex.py b/src/engine/SCons/Tool/tex.py index ce0a51f..23492fe 100644 --- a/src/engine/SCons/Tool/tex.py +++ b/src/engine/SCons/Tool/tex.py @@ -100,6 +100,10 @@ makeglossary_re = re.compile(r"^[^%\n]*\\makeglossary", re.MULTILINE) makeglossaries_re = re.compile(r"^[^%\n]*\\makeglossaries", re.MULTILINE) makeacronyms_re = re.compile(r"^[^%\n]*\\makeglossaries", re.MULTILINE) beamer_re = re.compile(r"^[^%\n]*\\documentclass\{beamer\}", re.MULTILINE) +regex = r'^[^%\n]*\\newglossary\s*\[([^\]]+)\]?\s*\{([^}]*)\}\s*\{([^}]*)\}\s*\{([^}]*)\}\s*\{([^}]*)\}' +newglossary_re = re.compile(regex, re.MULTILINE) + +newglossary_suffix = [] # search to find all files included by Latex include_re = re.compile(r'^[^%\n]*\\(?:include|input){([^}]*)}', re.MULTILINE) @@ -137,6 +141,9 @@ MakeGlossaryAction = None # An action to run MakeIndex (for acronyms) on a file. MakeAcronymsAction = None +# An action to run MakeIndex (for newglossary commands) on a file. +MakeNewGlossaryAction = None + # Used as a return value of modify_env_var if the variable is not set. _null = SCons.Scanner.LaTeX._null @@ -232,7 +239,8 @@ def InternalLaTeXAuxAction(XXXLaTeXAction, target = None, source= None, env=None saved_hashes = {} suffix_nodes = {} - for suffix in all_suffixes: + + for suffix in all_suffixes+sum(newglossary_suffix, []): theNode = env.fs.File(targetbase + suffix) suffix_nodes[suffix] = theNode saved_hashes[suffix] = theNode.get_csig() @@ -410,6 +418,21 @@ def InternalLaTeXAuxAction(XXXLaTeXAction, target = None, source= None, env=None 'alg') return result + # Now decide if latex will need to be run again due to newglossary command. + for ig in range(len(newglossary_suffix)): + if check_MD5(suffix_nodes[newglossary_suffix[ig][2]],newglossary_suffix[ig][2]) or (count == 1): + # We must run makeindex + if Verbose: + print "Need to run makeindex for newglossary" + newglfile = suffix_nodes[newglossary_suffix[ig][2]] + MakeNewGlossaryAction = SCons.Action.Action("$MAKENEWGLOSSARY ${SOURCE.filebase}%s -s ${SOURCE.filebase}.ist -t ${SOURCE.filebase}%s -o ${SOURCE.filebase}%s" % (newglossary_suffix[ig][2],newglossary_suffix[ig][0],newglossary_suffix[ig][1]), "$MAKENEWGLOSSARYCOMSTR") + + result = MakeNewGlossaryAction(newglfile, newglfile, env) + if result != 0: + check_file_error_message('%s (newglossary)' % env['MAKENEWGLOSSARY'], + newglossary_suffix[ig][0]) + return result + # Now decide if latex needs to be run yet again to resolve warnings. if warning_rerun_re.search(logContent): must_rerun_latex = True @@ -595,9 +618,27 @@ def ScanFiles(theFile, target, paths, file_tests, file_tests_search, env, graphi for i in range(len(file_tests_search)): if file_tests[i][0] is None: + if Verbose: + print "scan i ",i," files_tests[i] ",file_tests[i], file_tests[i][1] file_tests[i][0] = file_tests_search[i].search(content) if Verbose and file_tests[i][0]: - print " found match for ",file_tests[i][-1][-1] + print " found match for ",file_tests[i][1][-1] + # for newglossary insert the suffixes in file_tests[i] + if file_tests[i][0] and file_tests[i][1][-1] == 'newglossary': + findresult = file_tests_search[i].findall(content) + for l in range(len(findresult)) : + (file_tests[i][1]).insert(0,'.'+findresult[l][3]) + (file_tests[i][1]).insert(0,'.'+findresult[l][2]) + (file_tests[i][1]).insert(0,'.'+findresult[l][0]) + suffix_list = ['.'+findresult[l][0],'.'+findresult[l][2],'.'+findresult[l][3] ] + newglossary_suffix.append(suffix_list) + #newglossary_suffix.append('.'+findresult[l][0]) + #newglossary_suffix.append('.'+findresult[l][2]) + #newglossary_suffix.append('.'+findresult[l][3]) + #run_newglossary_suffix.append('.'+findresult[l][3]) + if Verbose: + print " new suffixes for newglossary ",newglossary_suffix + incResult = includeOnly_re.search(content) if incResult: @@ -676,7 +717,8 @@ def tex_emitter_core(target, source, env, graphics_extensions): makeglossary_re, makeglossaries_re, makeacronyms_re, - beamer_re ] + beamer_re, + newglossary_re ] # set up list with the file suffixes that need emitting # when a feature is found file_tests_suff = [['.aux','aux_file'], @@ -693,7 +735,9 @@ def tex_emitter_core(target, source, env, graphics_extensions): ['.glo', '.gls', '.glg','glossary'], ['.glo', '.gls', '.glg','glossaries'], ['.acn', '.acr', '.alg','acronyms'], - ['.nav', '.snm', '.out', '.toc','beamer'] ] + ['.nav', '.snm', '.out', '.toc','beamer'], + ['newglossary',] ] + # for newglossary the suffixes are added as we find the command # build the list of lists file_tests = [] for i in range(len(file_tests_search)): @@ -722,6 +766,7 @@ def tex_emitter_core(target, source, env, graphics_extensions): if Verbose: print "search path ",paths + # scan all sources for side effect files aux_files = [] file_tests = ScanFiles(source[0], target, paths, file_tests, file_tests_search, env, graphics_extensions, targetdir, aux_files) @@ -917,6 +962,9 @@ def generate_common(env): env['MAKENCLFLAGS'] = '-s ${MAKENCLSTYLE} -t ${SOURCE.filebase}.nlg' env['MAKENCLCOM'] = CDCOM + '${TARGET.dir} && $MAKENCL ${SOURCE.filebase}.nlo $MAKENCLFLAGS -o ${SOURCE.filebase}.nls' + env['MAKENEWGLOSSARY'] = 'makeindex' + env['MAKENEWGLOSSARYCOM'] = CDCOM + '${TARGET.dir} && $MAKENEWGLOSSARY ' + def exists(env): generate_darwin(env) return env.Detect('tex') diff --git a/test/TEX/newglossary.py b/test/TEX/newglossary.py new file mode 100644 index 0000000..12c68a7 --- /dev/null +++ b/test/TEX/newglossary.py @@ -0,0 +1,158 @@ +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +""" +Validate that use of \newglossary in TeX source files causes SCons to +be aware of the necessary created glossary files. + +Test configuration contributed by Robert Managan. +""" + +import os +import TestSCons + +test = TestSCons.TestSCons() + +latex = test.where_is('latex') + +if not latex: + test.skip_test("Could not find latex; skipping test(s).\n") + +gloss = os.system('kpsewhich glossaries.sty') +if not gloss==0: + test.skip_test("glossaries.sty not installed; skipping test(s).\n") + +test.write('SConstruct', """\ +import os +env = Environment() +env.PDF('newglossary', 'newglossary.tex') +""") + +test.write('newglossary.tex', r""" +\documentclass{report} + +% for glossary +\newlength{\symcol} +\newlength{\symw} +\newcommand{\symtab}[1]{\setlength{\symcol}{1.3cm}\settowidth{\symw}{\ensuremath{#1}}\advance\symcol by -\symw\hspace{\symcol}} +\newcommand{\newsym}[5]{\newglossaryentry{#1}{name=\ensuremath{#2},description={\symtab{#2}{#4}},parent={#5},sort={#3}}} +\newcommand{\newacronymf}[3]{\newglossaryentry{#1}{name={#2},description={#3},first={#2}}} + +\usepackage[acronym]{glossaries} +\newglossary[symlog]{symbol}{symi}{symo}{Symbols} +\newglossaryentry{nix}{ + name={Nix}, + description={Version 5} +} +\newglossary[deflog]{definition}{defi}{defo}{Definitions} +\newglossaryentry{defPower}{name=Ddyn,type={definition},description={def of 1 dynamic power consumption},sort={DP}} + +\newacronym{gnu}{GNU}{GNU's Not UNIX} +\makeglossaries +\glstoctrue +%\loadglsentries[\acronymtype]{chapters/acronyms} +\loadglsentries[symbol]{symbols} +%\loadglsentries[definition]{defns} + + +\begin{document} + +Here is a symbol: \gls{dynPower} and a glossary entry \gls{mel} + +Acronyms \gls{gnu} and glossary entries \gls{nix}. + +a definition \gls{defPower} + +\glossarystyle{index} +\printglossary[type=symbol] +\printglossary[type=acronym] +\printglossary[type=main] +\printglossary[type=definition] +\glossarystyle{super} + +\end{document}""") + + +test.write('symbols.tex', r""" +\newglossaryentry{mel}{name={Microelectronic Fundamentals},description={\nopostdesc},sort=d} +\newsym{dynPower}{P_{dyn}}{P}{Dynamic power consumption}{mel} + +%\newcommand{\newsym}[5]{\newglossaryentry{#1}{name=\ensuremath{#2},description={\symtab{#2}{#4}},parent={#5},sort={#3}}} +""") + +test.run(arguments = '.', stderr=None) + +test.must_exist(test.workpath('newglossary.acn')) +test.must_exist(test.workpath('newglossary.acr')) +test.must_exist(test.workpath('newglossary.alg')) +test.must_exist(test.workpath('newglossary.aux')) +test.must_exist(test.workpath('newglossary.defi')) +test.must_exist(test.workpath('newglossary.deflog')) +test.must_exist(test.workpath('newglossary.defo')) +test.must_exist(test.workpath('newglossary.fls')) +test.must_exist(test.workpath('newglossary.glg')) +test.must_exist(test.workpath('newglossary.glo')) +test.must_exist(test.workpath('newglossary.gls')) +test.must_exist(test.workpath('newglossary.ist')) +test.must_exist(test.workpath('newglossary.log')) +test.must_exist(test.workpath('newglossary.pdf')) +test.must_exist(test.workpath('newglossary.symi')) +test.must_exist(test.workpath('newglossary.symlog')) +test.must_exist(test.workpath('newglossary.symo')) + +test.run(arguments = '-c .') + +x = "Could not remove 'newglossary.aux': No such file or directory" +test.must_not_contain_any_line(test.stdout(), [x]) + +test.must_not_exist(test.workpath('newglossary.acn')) +test.must_not_exist(test.workpath('newglossary.acr')) +test.must_not_exist(test.workpath('newglossary.alg')) +test.must_not_exist(test.workpath('newglossary.defi')) +test.must_not_exist(test.workpath('newglossary.deflog')) +test.must_not_exist(test.workpath('newglossary.defo')) +test.must_not_exist(test.workpath('newglossary.aux')) +test.must_not_exist(test.workpath('newglossary.fls')) +test.must_not_exist(test.workpath('newglossary.glg')) +test.must_not_exist(test.workpath('newglossary.glo')) +test.must_not_exist(test.workpath('newglossary.gls')) +test.must_not_exist(test.workpath('newglossary.ist')) +test.must_not_exist(test.workpath('newglossary.log')) +test.must_not_exist(test.workpath('newglossary.pdf')) +test.must_not_exist(test.workpath('newglossary.symi')) +test.must_not_exist(test.workpath('newglossary.symlog')) +test.must_not_exist(test.workpath('newglossary.symo')) + +test.pass_test() + + + + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: -- cgit v0.12