diff options
Diffstat (limited to 'waflib/Tools/tex.py')
-rw-r--r-- | waflib/Tools/tex.py | 242 |
1 files changed, 242 insertions, 0 deletions
diff --git a/waflib/Tools/tex.py b/waflib/Tools/tex.py new file mode 100644 index 0000000..4a26c43 --- /dev/null +++ b/waflib/Tools/tex.py @@ -0,0 +1,242 @@ +#! /usr/bin/env python +# encoding: utf-8 +# WARNING! Do not edit! http://waf.googlecode.com/git/docs/wafbook/single.html#_obtaining_the_waf_file + +import os,re +from waflib import Utils,Task,Errors +from waflib.TaskGen import feature,before_method +from waflib.Logs import error,warn,debug +re_bibunit=re.compile(r'\\(?P<type>putbib)\[(?P<file>[^\[\]]*)\]',re.M) +def bibunitscan(self): + node=self.inputs[0] + nodes=[] + if not node:return nodes + code=Utils.readf(node.abspath()) + for match in re_bibunit.finditer(code): + path=match.group('file') + if path: + for k in['','.bib']: + debug('tex: trying %s%s'%(path,k)) + fi=node.parent.find_resource(path+k) + if fi: + nodes.append(fi) + else: + debug('tex: could not find %s'%path) + debug("tex: found the following bibunit files: %s"%nodes) + return nodes +exts_deps_tex=['','.ltx','.tex','.bib','.pdf','.png','.eps','.ps'] +exts_tex=['.ltx','.tex'] +re_tex=re.compile(r'\\(?P<type>include|bibliography|putbib|includegraphics|input|import|bringin|lstinputlisting)(\[[^\[\]]*\])?{(?P<file>[^{}]*)}',re.M) +g_bibtex_re=re.compile('bibdata',re.M) +class tex(Task.Task): + bibtex_fun,_=Task.compile_fun('${BIBTEX} ${BIBTEXFLAGS} ${SRCFILE}',shell=False) + bibtex_fun.__doc__=""" + Execute the program **bibtex** + """ + makeindex_fun,_=Task.compile_fun('${MAKEINDEX} ${MAKEINDEXFLAGS} ${SRCFILE}',shell=False) + makeindex_fun.__doc__=""" + Execute the program **makeindex** + """ + def scan_aux(self,node): + nodes=[node] + re_aux=re.compile(r'\\@input{(?P<file>[^{}]*)}',re.M) + def parse_node(node): + code=node.read() + for match in re_aux.finditer(code): + path=match.group('file') + found=node.parent.find_or_declare(path) + if found and found not in nodes: + debug('tex: found aux node '+found.abspath()) + nodes.append(found) + parse_node(found) + parse_node(node) + return nodes + def scan(self): + node=self.inputs[0] + nodes=[] + names=[] + seen=[] + if not node:return(nodes,names) + def parse_node(node): + if node in seen: + return + seen.append(node) + code=node.read() + global re_tex + for match in re_tex.finditer(code): + for path in match.group('file').split(','): + if path: + add_name=True + found=None + for k in exts_deps_tex: + debug('tex: trying %s%s'%(path,k)) + found=node.parent.find_resource(path+k) + if found and not found in self.outputs: + nodes.append(found) + add_name=False + for ext in exts_tex: + if found.name.endswith(ext): + parse_node(found) + break + if add_name: + names.append(path) + parse_node(node) + for x in nodes: + x.parent.get_bld().mkdir() + debug("tex: found the following : %s and names %s"%(nodes,names)) + return(nodes,names) + def check_status(self,msg,retcode): + if retcode!=0: + raise Errors.WafError("%r command exit status %r"%(msg,retcode)) + def bibfile(self): + need_bibtex=False + try: + for aux_node in self.aux_nodes: + ct=aux_node.read() + if g_bibtex_re.findall(ct): + need_bibtex=True + break + except(OSError,IOError): + error('error bibtex scan') + else: + if need_bibtex: + warn('calling bibtex') + self.env.env={} + self.env.env.update(os.environ) + self.env.env.update({'BIBINPUTS':self.TEXINPUTS,'BSTINPUTS':self.TEXINPUTS}) + self.env.SRCFILE=self.aux_nodes[0].name[:-4] + self.check_status('error when calling bibtex',self.bibtex_fun()) + def bibunits(self): + try: + bibunits=bibunitscan(self) + except FSError: + error('error bibunitscan') + else: + if bibunits: + fn=['bu'+str(i)for i in xrange(1,len(bibunits)+1)] + if fn: + warn('calling bibtex on bibunits') + for f in fn: + self.env.env={'BIBINPUTS':self.TEXINPUTS,'BSTINPUTS':self.TEXINPUTS} + self.env.SRCFILE=f + self.check_status('error when calling bibtex',self.bibtex_fun()) + def makeindex(self): + try: + idx_path=self.idx_node.abspath() + os.stat(idx_path) + except OSError: + warn('index file %s absent, not calling makeindex'%idx_path) + else: + warn('calling makeindex') + self.env.SRCFILE=self.idx_node.name + self.env.env={} + self.check_status('error when calling makeindex %s'%idx_path,self.makeindex_fun()) + def run(self): + env=self.env + if not env['PROMPT_LATEX']: + env.append_value('LATEXFLAGS','-interaction=batchmode') + env.append_value('PDFLATEXFLAGS','-interaction=batchmode') + env.append_value('XELATEXFLAGS','-interaction=batchmode') + fun=self.texfun + node=self.inputs[0] + srcfile=node.abspath() + texinputs=self.env.TEXINPUTS or'' + self.TEXINPUTS=node.parent.get_bld().abspath()+os.pathsep+node.parent.get_src().abspath()+os.pathsep+texinputs+os.pathsep + self.aux_node=node.change_ext('.aux') + self.cwd=self.inputs[0].parent.get_bld().abspath() + warn('first pass on %s'%self.__class__.__name__) + self.env.env={} + self.env.env.update(os.environ) + self.env.env.update({'TEXINPUTS':self.TEXINPUTS}) + self.env.SRCFILE=srcfile + self.check_status('error when calling latex',fun()) + self.aux_nodes=self.scan_aux(node.change_ext('.aux')) + self.idx_node=node.change_ext('.idx') + self.bibfile() + self.bibunits() + self.makeindex() + hash='' + for i in range(10): + prev_hash=hash + try: + hashes=[Utils.h_file(x.abspath())for x in self.aux_nodes] + hash=Utils.h_list(hashes) + except(OSError,IOError): + error('could not read aux.h') + pass + if hash and hash==prev_hash: + break + warn('calling %s'%self.__class__.__name__) + self.env.env={} + self.env.env.update(os.environ) + self.env.env.update({'TEXINPUTS':self.TEXINPUTS}) + self.env.SRCFILE=srcfile + self.check_status('error when calling %s'%self.__class__.__name__,fun()) +class latex(tex): + texfun,vars=Task.compile_fun('${LATEX} ${LATEXFLAGS} ${SRCFILE}',shell=False) +class pdflatex(tex): + texfun,vars=Task.compile_fun('${PDFLATEX} ${PDFLATEXFLAGS} ${SRCFILE}',shell=False) +class xelatex(tex): + texfun,vars=Task.compile_fun('${XELATEX} ${XELATEXFLAGS} ${SRCFILE}',shell=False) +class dvips(Task.Task): + run_str='${DVIPS} ${DVIPSFLAGS} ${SRC} -o ${TGT}' + color='BLUE' + after=['latex','pdflatex','xelatex'] +class dvipdf(Task.Task): + run_str='${DVIPDF} ${DVIPDFFLAGS} ${SRC} ${TGT}' + color='BLUE' + after=['latex','pdflatex','xelatex'] +class pdf2ps(Task.Task): + run_str='${PDF2PS} ${PDF2PSFLAGS} ${SRC} ${TGT}' + color='BLUE' + after=['latex','pdflatex','xelatex'] +def apply_tex(self): + if not getattr(self,'type',None)in['latex','pdflatex','xelatex']: + self.type='pdflatex' + tree=self.bld + outs=Utils.to_list(getattr(self,'outs',[])) + self.env['PROMPT_LATEX']=getattr(self,'prompt',1) + deps_lst=[] + if getattr(self,'deps',None): + deps=self.to_list(self.deps) + for filename in deps: + n=self.path.find_resource(filename) + if not n in deps_lst:deps_lst.append(n) + for node in self.to_nodes(self.source): + if self.type=='latex': + task=self.create_task('latex',node,node.change_ext('.dvi')) + elif self.type=='pdflatex': + task=self.create_task('pdflatex',node,node.change_ext('.pdf')) + elif self.type=='xelatex': + task=self.create_task('xelatex',node,node.change_ext('.pdf')) + task.env=self.env + if deps_lst: + try: + lst=tree.node_deps[task.uid()] + for n in deps_lst: + if not n in lst: + lst.append(n) + except KeyError: + tree.node_deps[task.uid()]=deps_lst + if self.type=='latex': + if'ps'in outs: + tsk=self.create_task('dvips',task.outputs,node.change_ext('.ps')) + tsk.env.env={'TEXINPUTS':node.parent.abspath()+os.pathsep+self.path.abspath()+os.pathsep+self.path.get_bld().abspath()} + if'pdf'in outs: + tsk=self.create_task('dvipdf',task.outputs,node.change_ext('.pdf')) + tsk.env.env={'TEXINPUTS':node.parent.abspath()+os.pathsep+self.path.abspath()+os.pathsep+self.path.get_bld().abspath()} + elif self.type=='pdflatex': + if'ps'in outs: + self.create_task('pdf2ps',task.outputs,node.change_ext('.ps')) + self.source=[] +def configure(self): + v=self.env + for p in'tex latex pdflatex xelatex bibtex dvips dvipdf ps2pdf makeindex pdf2ps'.split(): + try: + self.find_program(p,var=p.upper()) + except self.errors.ConfigurationError: + pass + v['DVIPSFLAGS']='-Ppdf' + +feature('tex')(apply_tex) +before_method('process_source')(apply_tex)
\ No newline at end of file |