summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/scripts/context/ruby/base/tex.rb
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2006-11-16 01:02:47 +0000
committerKarl Berry <karl@freefriends.org>2006-11-16 01:02:47 +0000
commit3c85b55e2f245fb7edac7e445f107e6d0bb423ae (patch)
treec62b7f80edafe0455310d08e09f4218127bf9e87 /Master/texmf-dist/scripts/context/ruby/base/tex.rb
parente5ecff27a26ef59e1dbe9702677687fd7107be3a (diff)
context update
git-svn-id: svn://tug.org/texlive/trunk@2444 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/scripts/context/ruby/base/tex.rb')
-rw-r--r--Master/texmf-dist/scripts/context/ruby/base/tex.rb1283
1 files changed, 881 insertions, 402 deletions
diff --git a/Master/texmf-dist/scripts/context/ruby/base/tex.rb b/Master/texmf-dist/scripts/context/ruby/base/tex.rb
index 2cc9d25422e..a6403dcde2b 100644
--- a/Master/texmf-dist/scripts/context/ruby/base/tex.rb
+++ b/Master/texmf-dist/scripts/context/ruby/base/tex.rb
@@ -8,8 +8,11 @@
# info : j.hagen@xs4all.nl
# www : www.pragma-ade.com
-# todo: write systemcall for mpost to file so that it can be run
-# faster
+# todo:
+#
+# - write systemcall for mpost to file so that it can be run faster
+# - use -8bit and -progname
+#
# report ?
@@ -20,6 +23,7 @@ require 'base/state'
require 'base/pdf'
require 'base/file'
require 'base/ctx'
+require 'base/mp'
class String
@@ -33,6 +37,12 @@ class String
end
+# class String
+ # def utf_bom?
+ # self.match(/^\357\273\277/o).length>0 rescue false
+ # end
+# end
+
class Array
def standard?
@@ -43,6 +53,10 @@ class Array
end
end
+ def join_path
+ self.join(File::PATH_SEPARATOR)
+ end
+
end
class TEX
@@ -56,6 +70,7 @@ class TEX
@@texengines = Hash.new
@@mpsengines = Hash.new
@@backends = Hash.new
+ @@mappaths = Hash.new
@@runoptions = Hash.new
@@texformats = Hash.new
@@mpsformats = Hash.new
@@ -68,11 +83,32 @@ class TEX
@@texmethods = Hash.new
@@mpsmethods = Hash.new
- ['tex','pdftex','pdfetex','standard'] .each do |e| @@texengines[e] = 'pdfetex' end
+ @@pdftex = 'pdftex' # new default, pdfetex is gone
+
+ ENV['PATH'].split(File::PATH_SEPARATOR).each do |p|
+ if System.unix? then
+ pp, pe = "#{p}/pdftex" , "#{p}/pdfetex"
+ else
+ pp, pe = "#{p}/pdftex.exe", "#{p}/pdfetex.exe"
+ end
+ if FileTest.file?(pe) then
+ # we assume no update
+ @@pdftex = 'pdfetex'
+ break
+ elsif FileTest.file?(pp) then
+ # we assume an update
+ @@pdftex = 'pdftex'
+ break
+ end
+ end
+
+ ['etex','pdfetex','standard'] .each do |e| @@texengines[e] = @@pdftex end
+ ['tex','pdftex'] .each do |e| @@texengines[e] = 'pdftex' end
['aleph','omega'] .each do |e| @@texengines[e] = 'aleph' end
['xetex'] .each do |e| @@texengines[e] = 'xetex' end
+ ['luatex'] .each do |e| @@texengines[e] = 'luatex' end
- ['metapost','mpost','standard'] .each do |e| @@mpsengines[e] = 'mpost' end
+ ['metapost','mpost', 'standard'] .each do |e| @@mpsengines[e] = 'mpost' end
['pdfetex','pdftex','pdf','pdftex','standard'] .each do |b| @@backends[b] = 'pdftex' end
['dvipdfmx','dvipdfm','dpx','dpm'] .each do |b| @@backends[b] = 'dvipdfmx' end
@@ -80,6 +116,13 @@ class TEX
['dvips','ps'] .each do |b| @@backends[b] = 'dvips' end
['dvipsone'] .each do |b| @@backends[b] = 'dvipsone' end
['acrobat','adobe','distiller'] .each do |b| @@backends[b] = 'acrobat' end
+ ['xdv','xdv2pdf'] .each do |b| @@backends[b] = 'xdv2pdf' end
+
+ ['tex','standard'] .each do |b| @@mappaths[b] = 'dvips' end
+ ['pdftex','pdfetex'] .each do |b| @@mappaths[b] = 'pdftex' end
+ ['aleph','omega','xetex'] .each do |b| @@mappaths[b] = 'dvipdfm' end
+ ['dvipdfm', 'dvipdfmx', 'xdvipdfmx'] .each do |b| @@mappaths[b] = 'dvipdfm' end
+ ['xdv','xdv2pdf'] .each do |b| @@mappaths[b] = 'dvips' end
# todo norwegian (no)
@@ -88,6 +131,7 @@ class TEX
['cont-nl','nl','dutch'] .each do |f| @@texformats[f] = 'cont-nl' end
['cont-de','de','german'] .each do |f| @@texformats[f] = 'cont-de' end
['cont-it','it','italian'] .each do |f| @@texformats[f] = 'cont-it' end
+ ['cont-fr','fr','french'] .each do |f| @@texformats[f] = 'cont-fr' end
['cont-cz','cz','czech'] .each do |f| @@texformats[f] = 'cont-cz' end
['cont-ro','ro','romanian'] .each do |f| @@texformats[f] = 'cont-ro' end
['cont-uk','uk','brittish'] .each do |f| @@texformats[f] = 'cont-uk' end
@@ -98,12 +142,13 @@ class TEX
['plain','mpost'] .each do |f| @@mpsformats[f] = 'plain' end
['metafun','context','standard'] .each do |f| @@mpsformats[f] = 'metafun' end
- ['pdfetex','aleph','omega'] .each do |p| @@prognames[p] = 'context' end
+ ['pdftex','pdfetex','aleph','omega',
+ 'xetex','luatex'] .each do |p| @@prognames[p] = 'context' end
['mpost'] .each do |p| @@prognames[p] = 'metafun' end
['plain','default','standard','mptopdf'] .each do |f| @@texmethods[f] = 'plain' end
['cont-en','cont-nl','cont-de','cont-it',
- 'cont-cz','cont-ro','cont-uk'] .each do |f| @@texmethods[f] = 'context' end
+ 'cont-fr','cont-cz','cont-ro','cont-uk'] .each do |f| @@texmethods[f] = 'context' end
['latex'] .each do |f| @@texmethods[f] = 'latex' end
['plain','default','standard'] .each do |f| @@mpsmethods[f] = 'plain' end
@@ -113,28 +158,35 @@ class TEX
@@mpsmakestr['plain'] = "\\dump"
['cont-en','cont-nl','cont-de','cont-it',
- 'cont-cz','cont-ro','cont-uk'] .each do |f| @@texprocstr[f] = "\\emergencyend" end
+ 'cont-fr','cont-cz','cont-ro','cont-uk'] .each do |f| @@texprocstr[f] = "\\emergencyend" end
- @@runoptions['xetex'] = ['--no-pdf']
+ # @@runoptions['xetex'] = ['--output-driver \\\"-d 4 -V 5\\\"'] # we need the pos pass
+ @@runoptions['xetex'] = ['--8bit -no-pdf'] # from now on we assume (x)dvipdfmx to be used
+ @@runoptions['pdfetex'] = ['--8bit ']
+ @@runoptions['pdftex'] = ['--8bit '] # pdftex is now pdfetex
+ @@runoptions['luatex'] = ['--8bit ']
+ @@runoptions['aleph'] = ['--8bit ']
@@booleanvars = [
'batchmode', 'nonstopmode', 'fast', 'fastdisabled', 'silentmode', 'final',
'paranoid', 'notparanoid', 'nobanner', 'once', 'allpatterns',
- 'nompmode', 'nomprun', 'automprun',
+ 'nompmode', 'nomprun', 'automprun', 'combine',
'nomapfiles', 'local',
'arrange', 'noarrange',
'forcexml', 'foxet',
+ 'alpha', 'beta',
'mpyforce', 'forcempy',
'forcetexutil', 'texutil',
'globalfile', 'autopath',
- 'purge', 'purgeall', 'autopdf', 'simplerun', 'verbose',
- 'nooptionfile'
+ 'purge', 'purgeall', 'keep', 'autopdf', 'xpdf', 'simplerun', 'verbose',
+ 'nooptionfile', 'nobackend', 'noctx', 'utfbom'
]
@@stringvars = [
'modefile', 'result', 'suffix', 'response', 'path',
'filters', 'usemodules', 'environments', 'separation', 'setuppath',
- 'arguments', 'input', 'output', 'randomseed', 'modes', 'filename',
- 'modefile', 'ctxfile'
+ 'arguments', 'input', 'output', 'randomseed', 'modes', 'mode', 'filename',
+ 'ctxfile', 'printformat', 'paperformat', 'paperoffset',
+ 'timeout'
]
@@standardvars = [
'mainlanguage', 'bodyfont', 'language'
@@ -148,16 +200,22 @@ class TEX
@@extrastringvars = []
def booleanvars
- [@@booleanvars,@@extrabooleanvars].flatten
+ [@@booleanvars,@@extrabooleanvars].flatten.uniq
end
def stringvars
- [@@stringvars,@@extrastringvars].flatten
+ [@@stringvars,@@extrastringvars].flatten.uniq
end
def standardvars
- @@standardvars
+ [@@standardvars].flatten.uniq
end
def knownvars
- @@knownvars
+ [@@knownvars].flatten.uniq
+ end
+ def allbooleanvars
+ [@@booleanvars,@@extrabooleanvars].flatten.uniq
+ end
+ def allstringvars
+ [@@stringvars,@@extrastringvars,@@standardvars,@@knownvars].flatten.uniq
end
def setextrastringvars(vars)
@@ -201,13 +259,18 @@ class TEX
setvariable('engine', 'standard') # replaced by tex/mpsengine
setvariable('backend', 'pdftex')
setvariable('runs', '8')
- setvariable('randomseed', rand(1440).to_s)
+ setvariable('randomseed', rand(1440).to_s) # we want the same seed for one run
# files
setvariable('files', [])
# defaults
setvariable('texengine', 'standard')
setvariable('mpsengine', 'standard')
setvariable('backend', 'standard')
+ setvariable('error', '')
+ end
+
+ def error?
+ not getvariable('error').empty?
end
def runtime
@@ -218,10 +281,17 @@ class TEX
report("runtime: #{runtime}")
end
+ def runcommand(something)
+ command = [something].flatten.join(' ')
+ report("running: #{command}") if getvariable('verbose')
+ system(command)
+ end
+
def inspect(name=nil)
if ! name || name.empty? then
name = [booleanvars,stringvars,standardvars,knownvars]
end
+ str = '' # allocate
[name].flatten.each do |n|
if str = getvariable(n) then
unless (str.class == String) && str.empty? then
@@ -249,11 +319,14 @@ class TEX
begin
Dir.glob("#{@@temprunfile}*").each do |name|
if File.file?(name) && (File.splitname(name)[1] !~ /(pdf|dvi)/o) then
- begin File.delete(name) ; rescue ; end
+ File.delete(name) rescue false
end
end
rescue
end
+ ['mpgraph.mp'].each do |file|
+ (File.delete(file) if (FileTest.size?(file) rescue 10) < 10) rescue false
+ end
end
def backends() @@backends.keys.sort end
@@ -301,11 +374,12 @@ class TEX
end
def prefixed(format,engine)
+ # format
case engine
- when /etex|eetex|pdfetex|pdfeetex|pdfxtex|xpdfetex|eomega|aleph|xetex/io then
- "*#{format}"
- else
- format
+ when /etex|pdftex|pdfetex|aleph|xetex|luatex/io then
+ "*#{format}"
+ else
+ format
end
end
@@ -318,18 +392,24 @@ class TEX
if str.class == String then str.split(',') else str.flatten end
end
- def validtexformat(str) validsomething(str,@@texformats) end
- def validmpsformat(str) validsomething(str,@@mpsformats) end
- def validtexengine(str) validsomething(str,@@texengines) end
- def validmpsengine(str) validsomething(str,@@mpsengines) end
+ def validtexformat(str) validsomething(str,@@texformats,'tex') end
+ def validmpsformat(str) validsomething(str,@@mpsformats,'mp' ) end
+ def validtexengine(str) validsomething(str,@@texengines,'pdfetex') end
+ def validmpsengine(str) validsomething(str,@@mpsengines,'mpost' ) end
def validtexmethod(str) [validsomething(str,@@texmethods)].flatten.first end
def validmpsmethod(str) [validsomething(str,@@mpsmethods)].flatten.first end
- def validsomething(str,something)
+ def validsomething(str,something,type=nil)
if str then
list = [str].flatten.collect do |s|
- something[s]
+ if something[s] then
+ something[s]
+ elsif type && s =~ /\.#{type}$/ then
+ s
+ else
+ nil
+ end
end .compact.uniq
if list.length>0 then
if str.class == String then list.first else list end
@@ -384,20 +464,20 @@ class TEX
# upward compatibility problems) but stuck to the bas/mem/fmt flags
if engine then
case validmpsengine(engine)
- when /mpost/ then "--mem"
- when /mfont/ then "--bas"
- else "--fmt"
+ when /mpost/ then "-mem"
+ when /mfont/ then "-bas"
+ else "-fmt"
end
else
- "--fmt"
+ "-fmt"
end
end
def prognameflag(progname=nil)
case getvariable('distribution')
- when 'standard' then prefix = "--progname"
- when /web2c/io then prefix = "--progname"
- when /miktex/io then prefix = "--alias"
+ when 'standard' then prefix = "-progname"
+ when /web2c/io then prefix = "-progname"
+ when /miktex/io then prefix = "-alias"
else return ""
end
if progname then
@@ -422,7 +502,7 @@ class TEX
if Kpse.miktex? then
"-tcx=#{file}"
else
- "--translate-file=#{file}"
+ "-translate-file=#{file}"
end
end
@@ -436,7 +516,7 @@ class TEX
filename = Kpse.found('context.tex')
version = 'unknown'
begin
- if FileTest.file?(filename) && IO.read(filename).match(/\\contextversion\{(\d+\.\d+\.\d+)\}/) then
+ if FileTest.file?(filename) && IO.read(filename).match(/\\contextversion\{(\d+\.\d+\.\d+.*?)\}/) then
version = $1
end
rescue
@@ -445,6 +525,10 @@ class TEX
end
def makeformats
+
+ checktestversion
+
+ report("using search method '#{Kpse.searchmethod}'")
if getvariable('fast') then
report('using existing database')
else
@@ -463,24 +547,27 @@ class TEX
# save current path
savedpath = Dir.getwd
# generate tex formats
+ unless texformats || mpsformats then
+ report('provide valid format (name.tex, name.mp, ...) or format id (metafun, en, nl, ...)')
+ end
if texformats && texengine && (progname = validprogname(getvariable('progname'),texengine)) then
report("using tex engine #{texengine}")
texformatpath = if getvariable('local') then '.' else Kpse.formatpath(texengine,true) end
# can be empty, to do
report("using tex format path #{texformatpath}")
- begin
- Dir.chdir(texformatpath)
- rescue
- end
- if texformats.length > 0 then
- makeuserfile
- makeresponsefile
- end
- texformats.each do |texformat|
- report("generating tex format #{texformat}")
- command = [quoted(texengine),prognameflag(progname),iniflag,tcxflag,prefixed(texformat,texengine),texmakeextras(texformat)].join(' ')
- report(command) if getvariable('verbose')
- system(command)
+ Dir.chdir(texformatpath) rescue false
+ if FileTest.writable?(texformatpath) then
+ if texformats.length > 0 then
+ makeuserfile
+ makeresponsefile
+ end
+ texformats.each do |texformat|
+ report("generating tex format #{texformat}")
+ runcommand([quoted(texengine),prognameflag(progname),iniflag,tcxflag,prefixed(texformat,texengine),texmakeextras(texformat)])
+ end
+ else
+ report("unable to make format due to lack of permissions")
+ texformatpath = ''
end
else
texformatpath = ''
@@ -490,15 +577,16 @@ class TEX
report("using mp engine #{mpsengine}")
mpsformatpath = if getvariable('local') then '.' else Kpse.formatpath(mpsengine,false) end
report("using mps format path #{mpsformatpath}")
- begin
- Dir.chdir(mpsformatpath)
- rescue
- end
- mpsformats.each do |mpsformat|
- report("generating mps format #{mpsformat}")
- command = [quoted(mpsengine),prognameflag(progname),iniflag,tcxflag,mpsformat,mpsmakeextras(mpsformat)].join(' ')
- report(command) if getvariable('verbose')
- system(command)
+ Dir.chdir(mpsformatpath) rescue false
+ if FileTest.writable?(mpsformatpath) then
+ mpsformats.each do |mpsformat|
+ report("generating mps format #{mpsformat}")
+ # runcommand([quoted(mpsengine),prognameflag(progname),iniflag,tcxflag,mpsformat,mpsmakeextras(mpsformat)])
+ runcommand([quoted(mpsengine),iniflag,tcxflag,mpsformat,mpsmakeextras(mpsformat)])
+ end
+ else
+ report("unable to make format due to lack of permissions")
+ mpsformatpath = ''
end
else
mpsformatpath = ''
@@ -560,7 +648,7 @@ class TEX
f.close
if FileTest.file?(tempfilename('tex')) then
format = File.basename(name)
- engine = if name =~ /(pdfetex|aleph|xetex)[\/\\]#{format}/ then $1 else '' end
+ engine = if name =~ /(pdftex|pdfetex|aleph|xetex|luatex)[\/\\]#{format}/ then $1 else '' end
if engine.empty? then
engineflag = ""
else
@@ -571,8 +659,8 @@ class TEX
interface = $1.sub(/cont\-/,'')
results.push('')
results.push("testing interface #{interface}")
- flags = ['--process','--batch','--once',"--interface=#{interface}",engineflag]
- # result = Kpse.pipescript('newtexexec',tempfilename,flags)
+ flags = ['--noctx','--process','--batch','--once',"--interface=#{interface}",engineflag]
+ # result = Kpse.pipescript('texexec',tempfilename,flags)
result = runtexexec([tempfilename], flags, 1)
if FileTest.file?("#{@@temprunfile}.log") then
logdata = IO.read("#{@@temprunfile}.log")
@@ -663,6 +751,7 @@ class TEX
@@preamblekeys = [
['tex','texengine'],
+ ['engine','texengine'],
['program','texengine'],
['translate','tcxfilter'],
['tcx','tcxfilter'],
@@ -670,22 +759,42 @@ class TEX
['mode','mode'],
['ctx','ctxfile'],
['version','contextversion'],
- ['format','texformat'],
- ['interface','texformat']
+ ['format','texformats'],
+ ['interface','texformats'],
]
+ @@re_utf_bom = /^\357\273\277/o
+
def scantexpreamble(filename)
begin
if FileTest.file?(filename) and tex = File.open(filename) then
+ bomdone = false
while str = tex.gets and str.chomp! do
+ unless bomdone then
+ if str.sub!(@@re_utf_bom, '')
+ report("utf mode forced (bom found)")
+ setvariable('utfbom',true)
+ end
+ bomdone = true
+ end
if str =~ /^\%\s*(.*)/o then
- vars = Hash.new
+ # we only accept lines with key=value pairs
+ vars, ok = Hash.new, true
$1.split(/\s+/o).each do |s|
k, v = s.split('=')
- vars[k] = v
+ if k && v then
+ vars[k] = v
+ else
+ ok = false
+ break
+ end
end
- @@preamblekeys.each do |v|
- setvariable(v[1],vars[v[0]]) if vars.key?(v[0])
+ if ok then
+ # we have a valid line
+ @@preamblekeys.each do |v|
+ setvariable(v[1],vars[v[0]]) if vars.key?(v[0]) && vars[v[0]]
+ end
+ break
end
else
break
@@ -699,37 +808,37 @@ class TEX
end
def scantexcontent(filename)
- if FileTest.file?(filename) and tex = File.open(filename) then
+ if FileTest.file?(filename) and tex = File.open(filename) then
while str = tex.gets do
case str.chomp
when /^\%/o then
# next
when /\\(starttekst|stoptekst|startonderdeel|startdocument|startoverzicht)/o then
- setvariable('texformat','nl') ; break
+ setvariable('texformats','nl') ; break
when /\\(stelle|verwende|umgebung|benutze)/o then
- setvariable('texformat','de') ; break
+ setvariable('texformats','de') ; break
when /\\(stel|gebruik|omgeving)/o then
- setvariable('texformat','nl') ; break
+ setvariable('texformats','nl') ; break
when /\\(use|setup|environment)/o then
- setvariable('texformat','en') ; break
+ setvariable('texformats','en') ; break
when /\\(usa|imposta|ambiente)/o then
- setvariable('texformat','it') ; break
+ setvariable('texformats','it') ; break
when /(height|width|style)=/o then
- setvariable('texformat','en') ; break
+ setvariable('texformats','en') ; break
when /(hoehe|breite|schrift)=/o then
- setvariable('texformat','de') ; break
+ setvariable('texformats','de') ; break
when /(hoogte|breedte|letter)=/o then
- setvariable('texformat','nl') ; break
+ setvariable('texformats','nl') ; break
when /(altezza|ampiezza|stile)=/o then
- setvariable('texformat','it') ; break
+ setvariable('texformats','it') ; break
when /externfiguur/o then
- setvariable('texformat','nl') ; break
+ setvariable('texformats','nl') ; break
when /externalfigure/o then
- setvariable('texformat','en') ; break
+ setvariable('texformats','en') ; break
when /externeabbildung/o then
- setvariable('texformat','de') ; break
+ setvariable('texformats','de') ; break
when /figuraesterna/o then
- setvariable('texformat','it') ; break
+ setvariable('texformats','it') ; break
end
end
tex.close
@@ -770,36 +879,11 @@ class TEX
end
end
- def makestubfile(rawname,forcexml=false)
- if tmp = File.open(File.suffixed(rawname,'run'),'w') then
+ def makestubfile(rawname,rawbase,forcexml=false)
+ if tmp = openedfile(File.suffixed(rawbase,'run')) then
tmp << "\\starttext\n"
if forcexml then
- if FileTest.file?(rawname) && (xml = File.open(rawname)) then
- xml.each do |line|
- case line
- when /<\?context\-directive\s+(\S+)\s+(\S+)\s+(\S+)\s*(.*?)\s*\?>/o then
- category, key, value, rest = $1, $2, $3, $4
- case category
- when 'job' then
- case key
- when 'control' then
- setvariable(value,if rest.empty? then true else rest end)
- when 'mode', 'modes' then
- tmp << "\\enablemode[#{value}]\n"
- when 'stylefile', 'environment' then
- tmp << "\\environment #{value}\n"
- when 'module' then
- tmp << "\\usemodule[#{value}]\n"
- when 'interface' then
- contextinterface = value
- end
- end
- when /<[a-z]+/io then # beware of order, first pi test
- break
- end
- end
- xml.close
- end
+ # tmp << checkxmlfile(rawname)
tmp << "\\processXMLfilegrouped{#{rawname}}\n"
else
tmp << "\\processfile{#{rawname}}\n"
@@ -812,16 +896,113 @@ class TEX
end
end
+ # def checkxmlfile(rawname)
+ # tmp = ''
+ # if FileTest.file?(rawname) && (xml = File.open(rawname)) then
+ # xml.each do |line|
+ # case line
+ # when /<\?context\-directive\s+(\S+)\s+(\S+)\s+(\S+)\s*(.*?)\s*\?>/o then
+ # category, key, value, rest = $1, $2, $3, $4
+ # case category
+ # when 'job' then
+ # case key
+ # when 'control' then
+ # setvariable(value,if rest.empty? then true else rest end)
+ # when 'mode', 'modes' then
+ # tmp << "\\enablemode[#{value}]\n"
+ # when 'stylefile', 'environment' then
+ # tmp << "\\environment #{value}\n"
+ # when 'module' then
+ # tmp << "\\usemodule[#{value}]\n"
+ # when 'interface' then
+ # contextinterface = value
+ # when 'ctxfile' then
+ # setvariable('ctxfile', value)
+ # report("using source driven ctxfile #{value}")
+ # end
+ # end
+ # when /<[a-z]+/io then # beware of order, first pi test
+ # break
+ # end
+ # end
+ # xml.close
+ # end
+ # return tmp
+ # end
+
+ def extendvariable(name,value)
+ set = getvariable(name).split(',')
+ set << value
+ str = set.uniq.join(',')
+ setvariable(name,str)
+ end
+
+ def checkxmlfile(rawname)
+ if FileTest.file?(rawname) && (xml = File.open(rawname)) then
+ xml.each do |line|
+ case line
+ when /<\?context\-directive\s+(\S+)\s+(\S+)\s+(\S+)\s*(.*?)\s*\?>/o then
+ category, key, value, rest = $1, $2, $3, $4
+ case category
+ when 'job' then
+ case key
+ when 'control' then
+ setvariable(value,if rest.empty? then true else rest end)
+ when /^(mode)(s|)$/ then
+ extendvariable('modes',value)
+ when /^(stylefile|environment)(s|)$/ then
+ extendvariable('environments',value)
+ when /^(use|)(module)(s|)$/ then
+ extendvariable('usemodules',value)
+ when /^(filter)(s|)$/ then
+ extendvariable('filters',value)
+ when 'interface' then
+ contextinterface = value
+ when 'ctxfile' then
+ setvariable('ctxfile', value)
+ report("using source driven ctxfile #{value}")
+ end
+ end
+ when /<[a-z]+/io then # beware of order, first pi test
+ break
+ end
+ end
+ xml.close
+ end
+ end
+
end
class TEX
+ def timedrun(delay, &block)
+ delay = delay.to_i rescue 0
+ if delay > 0 then
+ begin
+ report("job started with timeout '#{delay}'")
+ timeout(delay) do
+ yield block
+ end
+ rescue TimeoutError
+ report("job aborted due to timeout '#{delay}'")
+ rescue
+ report("job aborted due to error")
+ else
+ report("job finished within timeout '#{delay}'")
+ end
+ else
+ yield block
+ end
+ end
+
def processtex # much to do: mp, xml, runs etc
setvariable('texformats',[getvariable('interface')]) unless getvariable('interface').empty?
getarrayvariable('files').each do |filename|
setvariable('filename',filename)
report("processing document '#{filename}'")
- processfile
+ timedrun(getvariable('timeout')) do
+ processfile
+ end
end
reportruntime
end
@@ -835,152 +1016,284 @@ class TEX
reportruntime
end
+ private
+
+ def load_map_files(filename) # tui basename
+ # c \usedmapfile{=}{lm-texnansi}
+ begin
+ str = ""
+ IO.read(filename).scan(/^c\s+\\usedmapfile\{(.*?)\}\{(.*?)\}\s*$/o) do
+ str << "\\loadmapfile[#{$2}.map]\n"
+ end
+ rescue
+ return ""
+ else
+ return str
+ end
+ end
+
+ public
+
+ def processmpgraphic
+ getarrayvariable('files').each do |filename|
+ setvariable('filename',filename)
+ report("processing graphic '#{filename}'")
+ runtexmp(filename,'',false) # no purge
+ mapspecs = load_map_files(File.suffixed(filename,'temp','tui'))
+ unless getvariable('keep') then
+ # not enough: purge_mpx_files(filename)
+ Dir.glob(File.suffixed(filename,'temp*','*')).each do |fname|
+ File.delete(fname) unless File.basename(filename) == File.basename(fname)
+ end
+ end
+ begin
+ data = IO.read(File.suffixed(filename,'log'))
+ basename = filename.sub(/\.mp$/, '')
+ if data =~ /output files* written\:\s*(.*)$/mois then
+ files, number, range, list = $1.split(/\s+/), 0, false, []
+ files.each do |fname|
+ if fname =~ /^.*\.(\d+)$/ then
+ if range then
+ (number+1 .. $1.to_i).each do |i|
+ list << i
+ end
+ range = false
+ else
+ number = $1.to_i
+ list << number
+ end
+ elsif fname =~ /\.\./ then
+ range = true
+ else
+ range = false
+ next
+ end
+ end
+ begin
+ if getvariable('combine') then
+ fullname = "#{basename}.#{number}"
+ File.open("texexec.tex",'w') do |f|
+ f << "\\setupoutput[pdftex]\n"
+ f << "\\setupcolors[state=start]\n"
+ f << mapspecs
+ f << "\\starttext\n"
+ list.each do |number|
+ f << "\\startTEXpage\n"
+ f << "\\convertMPtoPDF{#{fullname}}{1}{1}"
+ f << "\\stopTEXpage\n"
+ end
+ f << "\\stoptext\n"
+ end
+ report("converting graphic '#{fullname}'")
+ runtex("texexec.tex")
+ pdffile = File.suffixed(basename,'pdf')
+ File.silentrename("texexec.pdf",pdffile)
+ report ("#{basename}.* converted to #{pdffile}")
+ else
+ list.each do |number|
+ begin
+ fullname = "#{basename}.#{number}"
+ File.open("texexec.tex",'w') do |f|
+ f << "\\setupoutput[pdftex]\n"
+ f << "\\setupcolors[state=start]\n"
+ f << mapspecs
+ f << "\\starttext\n"
+ f << "\\startTEXpage\n"
+ f << "\\convertMPtoPDF{#{fullname}}{1}{1}"
+ f << "\\stopTEXpage\n"
+ f << "\\stoptext\n"
+ end
+ report("converting graphic '#{fullname}'")
+ runtex("texexec.tex")
+ if files.length>1 then
+ pdffile = File.suffixed(basename,number.to_s,'pdf')
+ else
+ pdffile = File.suffixed(basename,'pdf')
+ end
+ File.silentrename("texexec.pdf",pdffile)
+ report ("#{fullname} converted to #{pdffile}")
+ end
+ end
+ end
+ rescue
+ report ("error when converting #{fullname} (#{$!})")
+ end
+ end
+ rescue
+ report("error in converting #{filename}")
+ end
+ end
+ reportruntime
+ end
+
def processmpxtex
getarrayvariable('files').each do |filename|
setvariable('filename',filename)
report("processing text of graphic '#{filename}'")
- processmpx(filename,true)
+ processmpx(filename,false,true,true)
end
reportruntime
end
def deleteoptionfile(rawname)
- begin
- File.delete(File.suffixed(rawname,'top'))
- rescue
+ ['top','top.keep'].each do |suffix|
+ begin
+ File.delete(File.suffixed(rawname,suffix))
+ rescue
+ end
end
end
- def makeoptionfile(rawname, jobname, jobsuffix, finalrun, fastdisabled, kindofrun)
- # jobsuffix = orisuffix
- if topname = File.suffixed(rawname,'top') and opt = File.open(topname,'w') then
- # local handies
- opt << "\% #{topname}\n"
- opt << "\\unprotect\n"
- opt << "\\setupsystem[\\c!n=#{kindofrun}]\n"
- opt << "\\def\\MPOSTformatswitch\{#{prognameflag('metafun')} #{formatflag('mpost')}=\}\n"
- if getvariable('batchmode') then
- opt << "\\batchmode\n"
- end
- if getvariable('nonstopmode') then
- opt << "\\nonstopmode\n"
- end
- if getvariable('paranoid') then
- opt << "\\def\\maxreadlevel{1}\n"
- end
- if (str = File.unixfied(getvariable('modefile'))) && ! str.empty? then
- opt << "\\readlocfile{#{str}}{}{}\n"
- end
- if (str = File.unixfied(getvariable('result'))) && ! str.empty? then
- opt << "\\setupsystem[file=#{str}]\n"
- elsif (str = getvariable('suffix')) && ! str.empty? then
- opt << "\\setupsystem[file=#{jobname}.#{str}]\n"
- end
- if (str = File.unixfied(getvariable('path'))) && ! str.empty? then
- opt << "\\usepath[#{str}]\n" unless str.empty?
- end
- if (str = getvariable('mainlanguage').downcase) && ! str.empty? && ! str.standard? then
- opt << "\\setuplanguage[#{str}]\n"
- end
- if str = validbackend(getvariable('backend')) then
- opt << "\\setupoutput[#{str}]\n"
- end
- if getvariable('color') then
- opt << "\\setupcolors[\\c!state=\\v!start]\n"
- end
- if getvariable('nompmode') || getvariable('nomprun') || getvariable('automprun') then
- opt << "\\runMPgraphicsfalse\n"
- end
- if getvariable('fast') && ! getvariable('fastdisabled') then
- opt << "\\fastmode\n"
- end
- if getvariable('silentmode') then
- opt << "\\silentmode\n"
- end
- if (str = getvariable('separation')) && ! str.empty? then
- opt << "\\setupcolors[\\c!split=#{str}]\n"
- end
- if (str = getvariable('setuppath')) && ! str.empty? then
- opt << "\\setupsystem[\\c!directory=\{#{str}\}]\n"
- end
- if (str = getvariable('paperformat')) && ! str.empty? && ! str.standard? then
- if str =~ /^([a-z]+\d+)([a-z]+\d+)$/io then # A5A4 A4A3 A2A1 ...
- opt << "\\setuppapersize[#{$1.upcase}][#{$2.upcase}]\n"
- else # ...*...
- pf = str.upcase.split(/[x\*]/o)
- pf << pf[0] if pd.size == 1
- opt << "\\setuppapersize[#{pf[0]}][#{pf[1]}]\n"
+ def makeoptionfile(rawname, jobname, jobsuffix, finalrun, fastdisabled, kindofrun, currentrun=1)
+ begin
+ # jobsuffix = orisuffix
+ if topname = File.suffixed(rawname,'top') and opt = File.open(topname,'w') then
+ report("writing option file #{topname}")
+ # local handies
+ opt << "\% #{topname}\n"
+ opt << "\\unprotect\n"
+ if getvariable('utfbom') then
+ opt << "\\enableregime[utf]"
end
- end
- if (str = getvariable('background')) && ! str.empty? then
- opt << "\\defineoverlay[whatever][{\\externalfigure[#{str}][\\c!factor=\\v!max]}]\n"
- opt << "\\setupbackgrounds[\\v!page][\\c!background=whatever]\n"
- end
- if getvariable('centerpage') then
- opt << "\\setuplayout[\\c!location=\\v!middle,\\c!marking=\\v!on]\n"
- end
- if getvariable('nomapfiles') then
- opt << "\\disablemapfiles\n"
- end
- if getvariable('noarrange') then
- opt << "\\setuparranging[\\v!disable]\n"
- elsif getvariable('arrange') then
- arrangement = Array.new
- if finalrun then
- arrangement << "\\v!doublesided" unless getvariable('noduplex')
- case printformat
- when '' then arrangement << "\\v!normal"
- when /.*up/oi then arrangement << "\\v!rotated"
- when /.*down/oi then arrangement << ["2DOWN","\\v!rotated"]
- when /.*side/oi then arrangement << ["2SIDE","\\v!rotated"]
+ opt << "\\setupsystem[\\c!n=#{kindofrun},\\c!m=#{currentrun}]\n"
+ opt << "\\def\\MPOSTformatswitch\{#{prognameflag('metafun')} #{formatflag('mpost')}=\}\n"
+ if getvariable('batchmode') then
+ opt << "\\batchmode\n"
+ end
+ if getvariable('nonstopmode') then
+ opt << "\\nonstopmode\n"
+ end
+ if getvariable('paranoid') then
+ opt << "\\def\\maxreadlevel{1}\n"
+ end
+ if (str = File.unixfied(getvariable('modefile'))) && ! str.empty? then
+ opt << "\\readlocfile{#{str}}{}{}\n"
+ end
+ if (str = File.unixfied(getvariable('result'))) && ! str.empty? then
+ opt << "\\setupsystem[file=#{str}]\n"
+ elsif (str = getvariable('suffix')) && ! str.empty? then
+ opt << "\\setupsystem[file=#{jobname}.#{str}]\n"
+ end
+ opt << "\\setupsystem[\\c!method=2]\n" # 1=oldtexexec 2=newtexexec (obsolete)
+ opt << "\\setupsystem[\\c!type=#{Tool.ruby_platform()}]\n"
+ if (str = File.unixfied(getvariable('path'))) && ! str.empty? then
+ opt << "\\usepath[#{str}]\n" unless str.empty?
+ end
+ if (str = getvariable('mainlanguage').downcase) && ! str.empty? && ! str.standard? then
+ opt << "\\setuplanguage[#{str}]\n"
+ end
+ if str = validbackend(getvariable('backend')) then
+ opt << "\\setupoutput[#{str}]\n"
+ elsif str = validbackend(getvariable('output')) then
+ opt << "\\setupoutput[#{str}]\n"
+ end
+ if getvariable('color') then
+ opt << "\\setupcolors[\\c!state=\\v!start]\n"
+ end
+ if getvariable('nompmode') || getvariable('nomprun') || getvariable('automprun') then
+ opt << "\\runMPgraphicsfalse\n"
+ end
+ if getvariable('fast') && ! getvariable('fastdisabled') then
+ opt << "\\fastmode\n"
+ end
+ if getvariable('silentmode') then
+ opt << "\\silentmode\n"
+ end
+ if (str = getvariable('separation')) && ! str.empty? then
+ opt << "\\setupcolors[\\c!split=#{str}]\n"
+ end
+ if (str = getvariable('setuppath')) && ! str.empty? then
+ opt << "\\setupsystem[\\c!directory=\{#{str}\}]\n"
+ end
+ if (str = getvariable('paperformat')) && ! str.empty? && ! str.standard? then
+ if str =~ /^([a-z]+\d+)([a-z]+\d+)$/io then # A5A4 A4A3 A2A1 ...
+ opt << "\\setuppapersize[#{$1.upcase}][#{$2.upcase}]\n"
+ else # ...*...
+ pf = str.upcase.split(/[x\*]/o)
+ pf << pf[0] if pf.size == 1
+ opt << "\\setuppapersize[#{pf[0]}][#{pf[1]}]\n"
end
- else
- arrangement << "\\v!disable"
end
- opt << "\\setuparranging[#{arrangement.flatten.join(',')}]\n" if arrangement.size > 0
- end
- if (str = getvariable('modes')) && ! str.empty? then
- opt << "\\enablemode[#{modes}]\n"
- end
- if (str = getvariable('arguments')) && ! str.empty? then
- opt << "\\setupenv[#{str}]\n"
- end
- if (str = getvariable('randomseed')) && ! str.empty? then
- opt << "\\setupsystem[\\c!random=#{str}]\n"
- end
- if (str = getvariable('input')) && ! str.empty? then
- opt << "\\setupsystem[inputfile=#{str}]\n"
- else
- opt << "\\setupsystem[inputfile=#{rawname}]\n"
- end
- if (str = getvariable('pages')) && ! str.empty? then
- if str.downcase == 'odd' then
- opt << "\\chardef\\whichpagetoshipout=1\n"
- elsif str.downcase == 'even' then
- opt << "\\chardef\\whichpagetoshipout=2\n"
+ if (str = getvariable('background')) && ! str.empty? then
+ opt << "\\defineoverlay[whatever][{\\externalfigure[#{str}][\\c!factor=\\v!max]}]\n"
+ opt << "\\setupbackgrounds[\\v!page][\\c!background=whatever]\n"
+ end
+ if getvariable('centerpage') then
+ opt << "\\setuplayout[\\c!location=\\v!middle,\\c!marking=\\v!on]\n"
+ end
+ if getvariable('nomapfiles') then
+ opt << "\\disablemapfiles\n"
+ end
+ if getvariable('noarrange') then
+ opt << "\\setuparranging[\\v!disable]\n"
+ elsif getvariable('arrange') then
+ arrangement = Array.new
+ if finalrun then
+ arrangement << "\\v!doublesided" unless getvariable('noduplex')
+ case getvariable('printformat')
+ when '' then arrangement << "\\v!normal"
+ when /.*up/oi then arrangement << ["2UP","\\v!rotated"]
+ when /.*down/oi then arrangement << ["2DOWN","\\v!rotated"]
+ when /.*side/oi then arrangement << ["2SIDE","\\v!rotated"]
+ end
+ else
+ arrangement << "\\v!disable"
+ end
+ opt << "\\setuparranging[#{arrangement.flatten.join(',')}]\n" if arrangement.size > 0
+ end
+ # we handle both "--mode" and "--modes", else "--mode" is
+ # mapped onto "--modefile"
+ if (str = getvariable('modes')) && ! str.empty? then
+ opt << "\\enablemode[#{str}]\n"
+ end
+ if (str = getvariable('mode')) && ! str.empty? then
+ opt << "\\enablemode[#{str}]\n"
+ end
+ if (str = getvariable('arguments')) && ! str.empty? then
+ opt << "\\setupenv[#{str}]\n"
+ end
+ if (str = getvariable('randomseed')) && ! str.empty? then
+ report("using randomseed #{str}")
+ opt << "\\setupsystem[\\c!random=#{str}]\n"
+ end
+ if (str = getvariable('input')) && ! str.empty? then
+ opt << "\\setupsystem[inputfile=#{str}]\n"
else
- pagelist = Array.new
- str.split(/\,/).each do |page|
- pagerange = page.split(/(\:|\.\.)/o )
- if pagerange.size > 1 then
- pagerange.first.to_i.upto(pagerange.last.to_i) do |p|
- pagelist << p.to_s
+ opt << "\\setupsystem[inputfile=#{rawname}]\n"
+ end
+ if (str = getvariable('pages')) && ! str.empty? then
+ if str.downcase == 'odd' then
+ opt << "\\chardef\\whichpagetoshipout=1\n"
+ elsif str.downcase == 'even' then
+ opt << "\\chardef\\whichpagetoshipout=2\n"
+ else
+ pagelist = Array.new
+ str.split(/\,/).each do |page|
+ pagerange = page.split(/\D+/o)
+ if pagerange.size > 1 then
+ pagerange.first.to_i.upto(pagerange.last.to_i) do |p|
+ pagelist << p.to_s
+ end
+ else
+ pagelist << page
end
- else
- pagelist << page
end
+ opt << "\\def\\pagestoshipout\{#{pagelist.join(',')}\}\n";
end
- opt << "\\def\\pagestoshipout\{pagelist.join(',')\}\n";
end
+ opt << "\\protect\n";
+ begin getvariable('filters' ).split(',').uniq.each do |f| opt << "\\useXMLfilter[#{f}]\n" end ; rescue ; end
+ begin getvariable('usemodules' ).split(',').uniq.each do |m| opt << "\\usemodule[#{m}]\n" end ; rescue ; end
+ begin getvariable('environments').split(',').uniq.each do |e| opt << "\\environment #{e}\n" end ; rescue ; end
+ # this will become:
+ # begin getvariable('environments').split(',').uniq.each do |e| opt << "\\useenvironment[#{e}]\n" end ; rescue ; end
+ opt << "\\endinput\n"
+ opt.close
+ else
+ report("unable to write option file #{topname}")
end
- opt << "\\protect\n";
- begin getvariable('filters' ).split(',').uniq.each do |f| opt << "\\useXMLfilter[#{f}]\n" end ; rescue ; end
- begin getvariable('usemodules' ).split(',').uniq.each do |m| opt << "\\usemodule[#{m}]\n" end ; rescue ; end
- begin getvariable('environments').split(',').uniq.each do |e| opt << "\\environment #{e}\n" end ; rescue ; end
- # this will become:
- # begin getvariable('environments').split(',').uniq.each do |e| opt << "\\useenvironment[#{e}]\n" end ; rescue ; end
- opt << "\\endinput\n"
- opt.close
+ rescue
+ report("fatal error in writing option file #{topname} (#{$!})")
end
end
@@ -1001,6 +1314,7 @@ class TEX
if ENV.key?('SHELL_ESCAPE') && (ENV['SHELL_ESCAPE'] == 'f') then
setvariable('automprun',true)
end
+ done = false
['TXRESOURCES','MPRESOURCES','MFRESOURCES'].each do |res|
[getvariable('runpath'),getvariable('path')].each do |pat|
unless pat.empty? then
@@ -1009,12 +1323,47 @@ class TEX
else
ENV[res] = pat
end
+ report("setting #{res} to #{ENV[res]}") unless done
end
end
+ done = true
end
end
+ def checktestversion
+ #
+ # one can set TEXMFALPHA and TEXMFBETA for test versions
+ # but keep in mind that the format as well as the test files
+ # then need the --alpha or --beta flag
+ #
+ done, tree = false, ''
+ ['alpha', 'beta'].each do |what|
+ if getvariable(what) then
+ if ENV["TEXMF#{what.upcase}"] then
+ done, tree = true, ENV["TEXMF#{what.upcase}"]
+ elsif ENV["TEXMFLOCAL"] then
+ done, tree = true, File.join(File.dirname(ENV['TEXMFLOCAL']), "texmf-#{what}")
+ end
+ end
+ break if done
+ end
+ if done then
+ tree = tree.strip
+ ENV['TEXMFPROJECT'] = tree
+ report("using test tree '#{tree}'")
+ ['MP', 'MF', 'TX'].each do |ctx|
+ ENV['CTXDEV#{ctx}PATH'] = ''
+ end
+ unless (FileTest.file?(File.join(tree,'ls-r')) || FileTest.file?(File.join(tree,'ls-R'))) then
+ report("no ls-r/ls-R file for tree '#{tree}' (run: mktexlsr #{tree})")
+ end
+ end
+ # puts `kpsewhich --expand-path=$TEXMF`
+ # exit
+ end
+
def runtex(filename)
+ checktestversion
texengine = validtexengine(getvariable('texengine'))
texformat = validtexformat(getarrayvariable('texformats').first)
progname = validprogname(getvariable('progname'))
@@ -1022,45 +1371,51 @@ class TEX
report("tex format: #{texformat}")
report("progname: #{progname}")
if texengine && texformat && progname then
- command = [quoted(texengine),prognameflag(progname),formatflag(texengine,texformat),runoptions(texengine),filename,texprocextras(texformat)].join(' ')
- report(command) if getvariable('verbose')
- system(command)
+ fixbackendvars(@@mappaths[texengine])
+ runcommand([quoted(texengine),prognameflag(progname),formatflag(texengine,texformat),tcxflag,runoptions(texengine),filename,texprocextras(texformat)])
+ # true
else
false
end
end
- def runmp(filename)
+ def runmp(mpname,mpx=false)
+ checktestversion
mpsengine = validmpsengine(getvariable('mpsengine'))
mpsformat = validmpsformat(getarrayvariable('mpsformats').first)
progname = validprogname(getvariable('progname'))
if mpsengine && mpsformat && progname then
- command = [quoted(mpsengine),prognameflag(progname),formatflag(mpsengine,mpsformat),runoptions(mpsengine),filename,mpsprocextras(mpsformat)].join(' ')
- report(command) if getvariable('verbose')
- system(command)
+ ENV["MPXCOMMAND"] = "0" unless mpx
+ # runcommand([quoted(mpsengine),prognameflag(progname),formatflag(mpsengine,mpsformat),tcxflag,runoptions(mpsengine),filename,mpsprocextras(mpsformat)])
+ runcommand([quoted(mpsengine),formatflag(mpsengine,mpsformat),tcxflag,runoptions(mpsengine),mpname,mpsprocextras(mpsformat)])
+ true
else
false
end
end
- def runtexmp(filename,filetype='')
- mpfile = File.suffixed(filename,filetype,'mp')
- if File.atleast?(mpfile,25) then
+ def runtexmp(filename,filetype='',purge=true)
+ checktestversion
+ mpname = File.suffixed(filename,filetype,'mp')
+ if File.atleast?(mpname,25) then
# first run needed
- File.silentdelete(File.suffixed(mpfile,'mpt'))
- doruntexmp(mpfile,false)
- mpgraphics = checkmpgraphics(mpfile)
- mplabels = checkmplabels(mpfile)
+ File.silentdelete(File.suffixed(mpname,'mpt'))
+ doruntexmp(mpname,nil,true,purge)
+ mpgraphics = checkmpgraphics(mpname)
+ mplabels = checkmplabels(mpname)
if mpgraphics || mplabels then
# second run needed
- doruntexmp(mpfile,mplabels)
+ doruntexmp(mpname,mplabels,true,purge)
+ else
+ # no labels
end
end
end
def runtexmpjob(filename,filetype='')
- mpfile = File.suffixed(filename,filetype,'mp')
- if File.atleast?(mpfile,25) && (data = File.silentread(mpfile)) then
+ checktestversion
+ mpname = File.suffixed(filename,filetype,'mp')
+ if File.atleast?(mpname,25) && (data = File.silentread(mpname)) then
textranslation = if data =~ /^\%\s+translate.*?\=([\w\d\-]+)/io then $1 else '' end
mpjobname = if data =~ /collected graphics of job \"(.+?)\"/io then $1 else '' end
if ! mpjobname.empty? and File.unsuffixed(filename) =~ /#{mpjobname}/ then # don't optimize
@@ -1071,8 +1426,9 @@ class TEX
options.push("--translate=#{textranslation}") unless textranslation.empty?
options.push("--batch") if getvariable('batchmode')
options.push("--nonstop") if getvariable('nonstopmode')
- options.push("--output=ps")
- return runtexexec(mpfile,options,2)
+ options.push("--output=ps") # options.push("--dvi")
+ options.push("--nobackend")
+ return runtexexec(mpname,options,2)
end
end
return false
@@ -1086,7 +1442,7 @@ class TEX
begin
logger = Logger.new('TeXUtil')
if tu = TeXUtil::Converter.new(logger) and tu.loaded(fname) then
- tu.saved if tu.processed
+ ok = tu.processed && tu.saved && tu.finalized
end
rescue
Kpse.runscript('texutil',fname,options)
@@ -1095,16 +1451,17 @@ class TEX
end
end
- # 1=tex 2=mptex 3=mpxtex
+ # 1=tex 2=mptex 3=mpxtex 4=mpgraphic
def runtexexec(filename=[], options=[], mode=nil)
begin
if mode and job = TEX.new(@logger) then
options.each do |option|
- if option=~ /^\-*(.*?)\=(.*)$/o then
- job.setvariable($1,$2)
- else
- job.setvariable(option,true)
+ case option
+ when /^\-*(.*?)\=(.*)$/o then
+ job.setvariable($1,$2)
+ when /^\-*(.*?)$/o then
+ job.setvariable($1,true)
end
end
job.setvariable("files",filename)
@@ -1112,6 +1469,7 @@ class TEX
when 1 then job.processtex
when 2 then job.processmptex
when 3 then job.processmpxtex
+ when 4 then job.processmpgraphic
end
job.inspect && Kpse.inspect if getvariable('verbose')
return true
@@ -1124,49 +1482,65 @@ class TEX
end
def fixbackendvars(backend)
- ENV['backend'] = backend ;
- ENV['progname'] = backend unless validtexengine(backend)
- ENV['TEXFONTMAPS'] = ".;\$TEXMF/fonts/map/{#{backend},pdftex,dvips,}//"
+ if backend then
+ report("fixing backend map path for #{backend}") if getvariable('verbose')
+ ENV['backend'] = backend ;
+ ENV['progname'] = backend unless validtexengine(backend)
+ ENV['TEXFONTMAPS'] = ['.',"\$TEXMF/fonts/map/{#{backend},pdftex,dvips,}//",'./fonts//'].join_path
+ else
+ report("unable to fix backend map path") if getvariable('verbose')
+ end
end
def runbackend(rawname)
- case validbackend(getvariable('backend'))
- when 'dvipdfmx' then
- fixbackendvars('dvipdfm')
- system("dvipdfmx -d 4 #{File.unsuffixed(rawname)}")
- when 'xetex' then
- fixbackendvars('xetex')
- system("xdv2pdf #{File.suffixed(jrawname,'xdv')}")
- when 'dvips' then
- fixbackendvars('dvips')
- mapfiles = ''
- begin
- if tuifile = File.suffixed(rawname,'tui') and FileTest.file?(tuifile) then
- IO.read(tuifile).scan(/^c \\usedmapfile\{.\}\{(.*?)\}\s*$/o) do
- mapfiles += "-u +#{$1} " ;
- end
+ unless getvariable('nobackend') then
+ case validbackend(getvariable('backend'))
+ when 'dvipdfmx' then
+ fixbackendvars('dvipdfm')
+ runcommand("dvipdfmx -d 4 -V 5 #{File.unsuffixed(rawname)}")
+ when 'xetex' then
+ # xetex now runs its own backend
+ xdvfile = File.suffixed(rawname,'xdv')
+ if FileTest.file?(xdvfile) then
+ fixbackendvars('dvipdfm')
+ runcommand("xdvipdfmx -d 4 -V 5 #{xdvfile}")
end
- rescue
+ when 'xdv2pdf' then
+ xdvfile = File.suffixed(rawname,'xdv')
+ if FileTest.file?(xdvfile) then
+ fixbackendvars('xdv2pdf')
+ runcommand("xdv2pdf #{xdvfile}")
+ end
+ when 'dvips' then
+ fixbackendvars('dvips')
mapfiles = ''
- end
- system("dvips #{mapfiles} #{File.unsuffixed(rawname)}")
- when 'pdftex' then
- # no need for postprocessing
- else
- report("no postprocessing needed")
+ begin
+ if tuifile = File.suffixed(rawname,'tui') and FileTest.file?(tuifile) then
+ IO.read(tuifile).scan(/^c \\usedmapfile\{.\}\{(.*?)\}\s*$/o) do
+ mapfiles += "-u +#{$1} " ;
+ end
+ end
+ rescue
+ mapfiles = ''
+ end
+ runcommand("dvips #{mapfiles} #{File.unsuffixed(rawname)}")
+ when 'pdftex' then
+ # no need for postprocessing
+ else
+ report("no postprocessing needed")
+ end
end
end
def processfile
takeprecautions
-
- rawname = getvariable('filename')
-
- jobname = getvariable('filename')
- suffix = getvariable('suffix')
- result = getvariable('result')
-
+ report("using search method '#{Kpse.searchmethod}'") if getvariable('verbose')
+ rawname = getvariable('filename')
+ jobname = getvariable('filename')
+ suffix = getvariable('suffix')
+ result = getvariable('result')
+ forcexml = getvariable('forcexml')
runonce = getvariable('once')
finalrun = getvariable('final') || (getvariable('arrange') && ! getvariable('noarrange'))
globalfile = getvariable('globalfile')
@@ -1188,9 +1562,13 @@ class TEX
setvariable('nomprun',true) if orisuffix == 'mpx' # else cylic run
+ PDFview.setmethod('xpdf') if getvariable('xpdf')
+
PDFview.closeall if getvariable('autopdf')
- forcexml = jobsuffix.match(/^(xml|fo|fox|rlg|exa)$/io) # nil or match
+ if jobsuffix =~ /^(htm|html|xhtml|xml|fo|fox|rlg|exa)$/io then
+ forcexml = true
+ end
dummyfile = false
@@ -1207,53 +1585,66 @@ class TEX
rawname = jobname + '.' + jobsuffix
+ rawpath = File.dirname(rawname)
+ rawbase = File.basename(rawname)
+
unless FileTest.file?(rawname) then
inppath.split(',').each do |ip|
break if dummyfile = FileTest.file?(File.join(ip,rawname))
end
end
+ if dummyfile || forcexml then
+ jobsuffix = makestubfile(rawname,rawbase,forcexml)
+ checkxmlfile(rawname)
+ end
+
+
# preprocess files
- ctx = CtxRunner.new(rawname,@logger)
- if getvariable('ctxfile').empty? then
- ctx.manipulate(File.suffixed(rawname,'ctx'),'jobname.ctx')
- else
- ctx.manipulate(File.suffixed(getvariable('ctxfile'),'ctx'))
- end
- ctx.savelog(File.suffixed(rawname,'ctl'))
+ unless getvariable('noctx') then
+ ctx = CtxRunner.new(rawname,@logger)
+ if getvariable('ctxfile').empty? then
+ if rawname == rawbase then
+ ctx.manipulate(File.suffixed(rawname,'ctx'),'jobname.ctx')
+ else
+ ctx.manipulate(File.suffixed(rawname,'ctx'),File.join(rawpath,'jobname.ctx'))
+ end
+ else
+ ctx.manipulate(File.suffixed(getvariable('ctxfile'),'ctx'))
+ end
+ ctx.savelog(File.suffixed(rawbase,'ctl'))
- envs = ctx.environments
- mods = ctx.modules
+ envs = ctx.environments
+ mods = ctx.modules
- # merge environment and module specs
+ # merge environment and module specs
- envs << getvariable('environments') unless getvariable('environments').empty?
- mods << getvariable('modules') unless getvariable('modules') .empty?
+ envs << getvariable('environments') unless getvariable('environments').empty?
+ mods << getvariable('modules') unless getvariable('modules') .empty?
- envs = envs.uniq.join(',')
- mods = mods.uniq.join(',')
+ envs = envs.uniq.join(',')
+ mods = mods.uniq.join(',')
- report("using environments #{envs}") if envs.length > 0
- report("using modules #{mods}") if mods.length > 0
+ report("using search method '#{Kpse.searchmethod}'") if getvariable('verbose')
+ report("using environments #{envs}") if envs.length > 0
+ report("using modules #{mods}") if mods.length > 0
- setvariable('environments', envs)
- setvariable('modules', mods)
+ setvariable('environments', envs)
+ setvariable('modules', mods)
+ end
# end of preprocessing and merging
- jobsuffix = makestubfile(rawname,forcexml) if dummyfile || forcexml
-
if globalfile || FileTest.file?(rawname) then
if not dummyfile and not globalfile then
scantexpreamble(rawname)
scantexcontent(rawname) if getvariable('texformats').standard?
end
-
result = File.suffixed(rawname,suffix) unless suffix.empty?
- pushresult(rawname,result)
+ pushresult(rawbase,result)
method = validtexmethod(validtexformat(getvariable('texformats')))
@@ -1263,64 +1654,114 @@ class TEX
when 'context' then
if getvariable('simplerun') || runonce then
- makeoptionfile(rawname,jobname,orisuffix,true,true,3) unless getvariable('nooptionfile')
- ok = runtex(rawname)
+ makeoptionfile(rawbase,jobname,orisuffix,true,true,3,1) unless getvariable('nooptionfile')
+ ok = runtex(if dummyfile || forcexml then rawbase else rawname end)
if ok then
- ok = runtexutil(rawname) if getvariable('texutil') || getvariable('forcetexutil')
- runbackend(rawname)
- popresult(rawname,result)
+ ok = runtexutil(rawbase) if getvariable('texutil') || getvariable('forcetexutil')
+ runbackend(rawbase)
+ popresult(rawbase,result)
+ end
+ if getvariable('keep') then
+ ['top','log','run'].each do |suffix|
+ File.silentrename(File.suffixed(rawbase,suffix),File.suffixed(rawbase,suffix+'.keep'))
+ end
end
- File.silentdelete(File.suffixed(rawname,'tmp'))
- File.silentrename(File.suffixed(rawname,'top'),File.suffixed(rawname,'tmp'))
else
mprundone, ok, stoprunning = false, true, false
texruns, nofruns = 0, getvariable('runs').to_i
state = FileState.new
['tub','tuo'].each do |s|
- state.register(File.suffixed(rawname,s))
+ state.register(File.suffixed(rawbase,s))
end
if getvariable('automprun') then # check this
['mprun','mpgraph'].each do |s|
- state.register(File.suffixed(rawname,s,'mp'),'randomseed')
+ state.register(File.suffixed(rawbase,s,'mp'),'randomseed')
end
end
while ! stoprunning && (texruns < nofruns) && ok do
texruns += 1
report("TeX run #{texruns}")
- if texruns == 1 then
- makeoptionfile(rawname,jobname,orisuffix,false,false,1) unless getvariable('nooptionfile')
- else
- makeoptionfile(rawname,jobname,orisuffix,false,false,2) unless getvariable('nooptionfile')
+ unless getvariable('nooptionfile') then
+ if texruns == nofruns then
+ makeoptionfile(rawbase,jobname,orisuffix,false,false,4,texruns) # last
+ elsif texruns == 1 then
+ makeoptionfile(rawbase,jobname,orisuffix,false,false,1,texruns) # first
+ else
+ makeoptionfile(rawbase,jobname,orisuffix,false,false,2,texruns) # unknown
+ end
end
- ok = runtex(File.suffixed(rawname,jobsuffix))
+ ok = runtex(File.suffixed(if dummyfile || forcexml then rawbase else rawname end,jobsuffix))
if ok && (nofruns > 1) then
unless getvariable('nompmode') then
- mprundone = runtexmpjob(rawname, "mpgraph")
- mprundone = runtexmpjob(rawname, "mprun")
+ mprundone = runtexmpjob(rawbase, "mpgraph")
+ mprundone = runtexmpjob(rawbase, "mprun")
end
- ok = runtexutil(rawname)
+ ok = runtexutil(rawbase)
state.update
stoprunning = state.stable?
end
end
- ok = runtexutil(rawname) if (nofruns == 1) && getvariable('texutil')
+ if not ok then
+ setvariable('error','error in tex file')
+ end
+ ok = runtexutil(rawbase) if (nofruns == 1) && getvariable('texutil')
if ok && finalrun && (nofruns > 1) then
- makeoptionfile(rawname,jobname,orisuffix,true,finalrun,4) unless getvariable('nooptionfile')
+ makeoptionfile(rawbase,jobname,orisuffix,true,finalrun,4,texruns) unless getvariable('nooptionfile')
report("final TeX run #{texruns}")
- ok = runtex(File.suffixed(rawname,jobsuffix))
+ ok = runtex(File.suffixed(if dummyfile || forcexml then rawbase else rawname end,jobsuffix))
end
- ['tmp','top'].each do |s| # previous tuo file / runtime option file
- File.silentdelete(File.suffixed(rawname,s))
+ if getvariable('keep') then
+ ['top','log','run'].each do |suffix|
+ File.silentrename(File.suffixed(rawbase,suffix),File.suffixed(rawbase,suffix+'.keep'))
+ end
+ else
+ File.silentrename(File.suffixed(rawbase,'top'),File.suffixed(rawbase,'tmp'))
end
- File.silentrename(File.suffixed(rawname,'top'),File.suffixed(rawname,'tmp'))
+ # ['tmp','top','log'].each do |s| # previous tuo file / runtime option file / log file
+ # File.silentdelete(File.suffixed(rawbase,s))
+ # end
if ok then
- runbackend(rawname)
- popresult(rawname,result)
+ runbackend(rawbase)
+ popresult(rawbase,result)
+ end
+ if true then # autopurge
+ begin
+ File.open(File.suffixed(rawbase, 'tuo')) do |f|
+ ok = 0
+ f.each do |line|
+ case ok
+ when 1 then
+ # next line is empty
+ ok = 2
+ when 2 then
+ if line =~ /^\%\s+\>\s+(.*?)\s+(\d+)/mois then
+ filename, n = $1, $2
+ done = File.delete(filename) rescue false
+ if done && getvariable('verbose') then
+ report("deleting #{filename} (#{n} times used)")
+ end
+ else
+ break
+ end
+ else
+ if line =~ /^\%\s+temporary files\:\s+(\d+)/mois then
+ if $1.to_i == 0 then
+ break
+ else
+ ok = 1
+ end
+ end
+ end
+ end
+ end
+ rescue
+ report("fatal error #{$!}")
+ end
end
end
- Kpse.runscript('ctxtools',rawname,'--purge') if getvariable('purge')
- Kpse.runscript('ctxtools',rawname,'--purgeall') if getvariable('purgeall')
+ Kpse.runscript('ctxtools',rawbase,'--purge') if getvariable('purge')
+ Kpse.runscript('ctxtools',rawbase,'--purge --all') if getvariable('purgeall')
when 'latex' then
@@ -1332,63 +1773,61 @@ class TEX
end
- if (dummyfile or forcexml) and FileTest.file?(rawname) then
+ if (dummyfile or forcexml) and FileTest.file?(rawbase) then
begin
- File.delete(File.suffixed(rawname,'run'))
+ File.delete(File.suffixed(rawbase,'run'))
rescue
report("unable to delete stub file")
end
end
if ok and getvariable('autopdf') then
- PDFview.open(File.suffixed(if result.empty? then rawname else result end,'pdf'))
+ PDFview.open(File.suffixed(if result.empty? then rawbase else result end,'pdf'))
end
+ else
+ report("nothing to process")
end
end
- # mp specific
+ # The labels are collected in the mergebe hash. Here we merge the relevant labels
+ # into beginfig/endfig. We could as well do this in metafun itself. Maybe some
+ # day ... (it may cost a bit of string space but that is cheap nowadays).
- def doruntexmp(mpname,mergebe=true,context=true)
+ def doruntexmp(mpname,mergebe=nil,context=true,purge=true)
texfound = false
- mpbetex = Hash.new
- mpfile = File.suffixed(mpname,'mp')
- mpcopy = File.suffixed(mpname,'copy','mp')
- setvariable('mp.file',mpfile)
+ mpname = File.suffixed(mpname,'mp')
+ mpcopy = File.suffixed(mpname,'mp.copy')
+ mpkeep = File.suffixed(mpname,'mp.keep')
+ setvariable('mp.file',mpname)
setvariable('mp.line','')
setvariable('mp.error','')
- if mpdata = File.silentread(mpfile) then
+ if mpdata = File.silentread(mpname) then
mpdata.gsub!(/^\#.*\n/o,'')
- File.silentrename(mpfile,mpcopy)
- texfound = mergebe || mpdata =~ /btex .*? etex/o
- if mp = File.silentopen(mpfile,'w') then
- mpdata.gsub!(/(btex.*?)\;(.*?etex)/o) do "#{$1}@@@#{$2}" end
- mpdata.gsub!(/(\".*?)\;(.*?\")/o) do "#{$1}@@@#{$2}" end
- mpdata.gsub!(/\;/o, "\;\n")
- mpdata.gsub!(/\n+/o, "\n")
- mpdata.gsub!(/(btex.*?)@@@(.*?etex)/o) do "#{$1}\;#{$2}" end
- mpdata.gsub!(/(\".*?)@@@(.*?\")/o) do "#{$1};#{$2}" end
+ File.silentrename(mpname,mpcopy)
+ texfound = mergebe || (mpdata =~ /btex .*? etex/mo)
+ if mp = openedfile(mpname) then
if mergebe then
- mpdata.gsub!(/beginfig\s*\((\d+)\)\s*\;(.*?)endfig\s*\;/o) do
+ mpdata.gsub!(/beginfig\s*\((\d+)\)\s*\;(.+?)endfig\s*\;/mo) do
n, str = $1, $2
- if str =~ /(.*?)(verbatimtex.*?etex)\s*\;(.*)/o then
- "beginfig(#{n})\;\n$1$2\;\n#{mpbetex(n)}\n$3\;endfig\;\n"
+ if str =~ /^(.*?)(verbatimtex.*?etex)\s*\;(.*)$/mo then
+ "beginfig(#{n})\;\n#{$1}#{$2}\;\n#{mergebe[n]}\n#{$3}\;endfig\;\n"
else
- "beginfig(#{n})\;\n#{mpbetex(n)}\n#{str}\;endfig\;\n"
+ "beginfig(#{n})\;\n#{mergebe[n]}\n#{str}\;endfig\;\n"
end
end
+ unless mpdata =~ /beginfig\s*\(\s*0\s*\)/o then
+ mp << mergebe['0'] if mergebe.key?('0')
+ end
end
- unless mpdata =~ /beginfig\s*\(\s*0\s*\)/o then
- mp << mpbetex[0] if mpbetex.key?(0)
- end
- mp << mpdata # ??
+ mp << MPTools::splitmplines(mpdata)
mp << "\n"
mp << "end"
mp << "\n"
mp.close
end
- processmpx(mpname) if texfound
+ processmpx(mpname,true,true,purge) if texfound
if getvariable('batchmode') then
options = ' --interaction=batch'
elsif getvariable('nonstopmode') then
@@ -1398,7 +1837,7 @@ class TEX
end
# todo plain|mpost|metafun
ok = runmp(mpname)
- if f = File.silentopen(File.suffixed(mpfile,'log')) then
+ if f = File.silentopen(File.suffixed(mpname,'log')) then
while str = f.gets do
if str =~ /^l\.(\d+)\s(.*?)\n/o then
setvariable('mp.line',$1)
@@ -1408,32 +1847,63 @@ class TEX
end
f.close
end
- File.silentrename(mpfile,"mptrace.tmp")
- File.silentrename(mpcopy, mpfile)
+ File.silentrename(mpname, mpkeep)
+ File.silentrename(mpcopy, mpname)
end
end
- def processmpx(mpname,context=true)
- mpname = File.suffixed(mpname,'mp')
- if File.atleast?(mpname,10) && (data = File.silentread(mpname)) then
+ # todo: use internal mptotext function and/or turn all btex/etex into textexts
+
+ def processmpx(mpname,force=false,context=true,purge=true)
+ unless force then
+ mpname = File.suffixed(mpname,'mp')
+ if File.atleast?(mpname,10) && (data = File.silentread(mpname)) then
+ if data =~ /(btex|etex|verbatimtex|textext)/o then
+ force = true
+ end
+ end
+ end
+ if force then
begin
- if data =~ /(btex|etex|verbatimtex)/o then
- mptex = File.suffixed(mpname,'temp','tex')
- mpdvi = File.suffixed(mpname,'temp','dvi')
- mplog = File.suffixed(mpname,'temp','log')
- mpmpx = File.suffixed(mpname,'temp','mpx')
- ok = system("mpto #{mpname} > #{mptex}")
- if ok && File.appended(mptex, "\\end\n") then
+ mptex = File.suffixed(mpname,'temp','tex')
+ mpdvi = File.suffixed(mpname,'temp','dvi')
+ mplog = File.suffixed(mpname,'temp','log')
+ mpmpx = File.suffixed(mpname,'mpx')
+ File.silentdelete(mptex)
+ if true then
+ report("using internal mptotex converter")
+ ok = MPTools::mptotex(mpname,mptex,'context')
+ else
+ command = "mpto #{mpname} > #{mptex}"
+ report(command) if getvariable('verbose')
+ ok = system(command)
+ end
+ # not "ok && ..." because of potential problem with return code and redirect (>)
+ if FileTest.file?(mptex) && File.appended(mptex, "\\end\n") then
+ # to be replaced by runtexexec([filenames],options,1)
+ if localjob = TEX.new(@logger) then
+ localjob.setvariable('files',mptex)
+ localjob.setvariable('backend','dvips')
+ localjob.setvariable('engine',getvariable('engine')) unless getvariable('engine').empty?
+ localjob.setvariable('once',true)
+ localjob.setvariable('nobackend',true)
if context then
- ok = RunConTeXtFile(mptex)
+ localjob.setvariable('texformats',[getvariable('interface')]) unless getvariable('interface').empty?
+ elsif getvariable('interface').empty? then
+ localjob.setvariable('texformats',['plain'])
else
- ok = RunSomeTeXFile(mptex)
- end
- ok = ok && FileTest.file?(mpdvi) && system("dvitomp #{mpdvi} #{mpmpx}")
- [mptex,mpdvi,mplog].each do |mpfil|
- File.silentdelete(mpfil)
+ localjob.setvariable('texformats',[getvariable('interface')])
end
+ localjob.processtex
+ ok = true # todo
+ else
+ ok = false
end
+ # so far
+ command = "dvitomp #{mpdvi} #{mpmpx}"
+ report(command) if getvariable('verbose')
+ ok = ok && FileTest.file?(mpdvi) && system(command)
+ purge_mpx_files(mpname) if purge
end
rescue
# error in processing mpx file
@@ -1441,6 +1911,14 @@ class TEX
end
end
+ def purge_mpx_files(mpname)
+ unless getvariable('keep') then
+ ['tex', 'log', 'tui', 'tuo', 'top'].each do |suffix|
+ File.silentdelete(File.suffixed(mpname,'temp',suffix))
+ end
+ end
+ end
+
def checkmpgraphics(mpname)
mpoptions = ''
if getvariable('makempy') then
@@ -1452,12 +1930,12 @@ class TEX
mponame = File.suffixed(mpname,'mpo')
mpyname = File.suffixed(mpname,'mpy')
return false unless File.atleast?(mponame,32)
- mpochecksum = State.new.checksum(mponame)
+ mpochecksum = FileState.new.checksum(mponame)
return false if mpochecksum.empty?
# where does the checksum get into the file?
# maybe let texexec do it?
# solution: add one if not present or update when different
- if f = File.open(mpyname) then
+ if f = File.silentopen(mpyname) then
str = f.gets.chomp
f.close
if str =~ /^\%\s*mpochecksum\s*\:\s*(\d+)/o then
@@ -1470,24 +1948,25 @@ class TEX
def checkmplabels(mpname)
mpname = File.suffixed(mpname,'mpt')
- if File.atleast?(mpname,10) && (mp = File.open(mpname)) then
+ if File.atleast?(mpname,10) && (mp = File.silentopen(mpname)) then
labels = Hash.new
while str = mp.gets do
- if str =~ /%\s*setup\s*:\s*(.*)/o then
- t = $1
- else
- t = ''
- end
- if str =~ /%\s*figure\s*(\d+)\s*:\s*(.*)/o then
+ t = if str =~ /^%\s*setup\s*:\s*(.*)$/o then $1 else '' end
+ if str =~ /^%\s*figure\s*(\d+)\s*:\s*(.*)$/o then
+ labels[$1] = labels[$1] || ''
unless t.empty? then
labels[$1] += "#{t}\n"
t = ''
end
- labels[$1] += "$2\n"
+ labels[$1] += "#{$2}\n"
end
end
mp.close
- return labels if labels.size>0
+ if labels.size>0 then
+ return labels
+ else
+ return nil
+ end
end
return nil
end