aboutsummaryrefslogtreecommitdiff
path: root/waflib/Tools/tex.py
diff options
context:
space:
mode:
Diffstat (limited to 'waflib/Tools/tex.py')
-rw-r--r--waflib/Tools/tex.py242
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