summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/scripts/context/ruby/base/tex.rb
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/scripts/context/ruby/base/tex.rb')
-rw-r--r--Master/texmf-dist/scripts/context/ruby/base/tex.rb1495
1 files changed, 1495 insertions, 0 deletions
diff --git a/Master/texmf-dist/scripts/context/ruby/base/tex.rb b/Master/texmf-dist/scripts/context/ruby/base/tex.rb
new file mode 100644
index 00000000000..2cc9d25422e
--- /dev/null
+++ b/Master/texmf-dist/scripts/context/ruby/base/tex.rb
@@ -0,0 +1,1495 @@
+# module : base/tex
+# copyright : PRAGMA Advanced Document Engineering
+# version : 2005
+# author : Hans Hagen
+#
+# project : ConTeXt / eXaMpLe
+# concept : Hans Hagen
+# info : j.hagen@xs4all.nl
+# www : www.pragma-ade.com
+
+# todo: write systemcall for mpost to file so that it can be run
+# faster
+
+# report ?
+
+require 'base/variables'
+require 'base/kpse'
+require 'base/system'
+require 'base/state'
+require 'base/pdf'
+require 'base/file'
+require 'base/ctx'
+
+class String
+
+ def standard?
+ begin
+ self == 'standard'
+ rescue
+ false
+ end
+ end
+
+end
+
+class Array
+
+ def standard?
+ begin
+ self.include?('standard')
+ rescue
+ false
+ end
+ end
+
+end
+
+class TEX
+
+ # The make-part of this class was made on a rainy day while listening
+ # to "10.000 clowns on a rainy day" by Jan Akkerman. Unfortunately the
+ # make method is not as swinging as this live cd.
+
+ include Variables
+
+ @@texengines = Hash.new
+ @@mpsengines = Hash.new
+ @@backends = Hash.new
+ @@runoptions = Hash.new
+ @@texformats = Hash.new
+ @@mpsformats = Hash.new
+ @@prognames = Hash.new
+ @@texmakestr = Hash.new
+ @@texprocstr = Hash.new
+ @@mpsmakestr = Hash.new
+ @@mpsprocstr = Hash.new
+
+ @@texmethods = Hash.new
+ @@mpsmethods = Hash.new
+
+ ['tex','pdftex','pdfetex','standard'] .each do |e| @@texengines[e] = 'pdfetex' end
+ ['aleph','omega'] .each do |e| @@texengines[e] = 'aleph' end
+ ['xetex'] .each do |e| @@texengines[e] = 'xetex' 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
+ ['xetex','xtx'] .each do |b| @@backends[b] = 'xetex' end
+ ['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
+
+ # todo norwegian (no)
+
+ ['plain'] .each do |f| @@texformats[f] = 'plain' end
+ ['cont-en','en','english','context','standard'].each do |f| @@texformats[f] = 'cont-en' end
+ ['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-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
+ ['mptopdf'] .each do |f| @@texformats[f] = 'mptopdf' end
+
+ ['latex'] .each do |f| @@texformats[f] = 'latex.ltx' end
+
+ ['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
+ ['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
+ ['latex'] .each do |f| @@texmethods[f] = 'latex' end
+
+ ['plain','default','standard'] .each do |f| @@mpsmethods[f] = 'plain' end
+ ['metafun'] .each do |f| @@mpsmethods[f] = 'metafun' end
+
+ @@texmakestr['plain'] = "\\dump"
+ @@mpsmakestr['plain'] = "\\dump"
+
+ ['cont-en','cont-nl','cont-de','cont-it',
+ 'cont-cz','cont-ro','cont-uk'] .each do |f| @@texprocstr[f] = "\\emergencyend" end
+
+ @@runoptions['xetex'] = ['--no-pdf']
+
+ @@booleanvars = [
+ 'batchmode', 'nonstopmode', 'fast', 'fastdisabled', 'silentmode', 'final',
+ 'paranoid', 'notparanoid', 'nobanner', 'once', 'allpatterns',
+ 'nompmode', 'nomprun', 'automprun',
+ 'nomapfiles', 'local',
+ 'arrange', 'noarrange',
+ 'forcexml', 'foxet',
+ 'mpyforce', 'forcempy',
+ 'forcetexutil', 'texutil',
+ 'globalfile', 'autopath',
+ 'purge', 'purgeall', 'autopdf', 'simplerun', 'verbose',
+ 'nooptionfile'
+ ]
+ @@stringvars = [
+ 'modefile', 'result', 'suffix', 'response', 'path',
+ 'filters', 'usemodules', 'environments', 'separation', 'setuppath',
+ 'arguments', 'input', 'output', 'randomseed', 'modes', 'filename',
+ 'modefile', 'ctxfile'
+ ]
+ @@standardvars = [
+ 'mainlanguage', 'bodyfont', 'language'
+ ]
+ @@knownvars = [
+ 'engine', 'distribution', 'texformats', 'mpsformats', 'progname', 'interface',
+ 'runs', 'backend'
+ ]
+
+ @@extrabooleanvars = []
+ @@extrastringvars = []
+
+ def booleanvars
+ [@@booleanvars,@@extrabooleanvars].flatten
+ end
+ def stringvars
+ [@@stringvars,@@extrastringvars].flatten
+ end
+ def standardvars
+ @@standardvars
+ end
+ def knownvars
+ @@knownvars
+ end
+
+ def setextrastringvars(vars)
+ @@extrastringvars << vars
+ end
+ def setextrabooleanvars(vars)
+ @@extrabooleanvars << vars
+ end
+
+ @@temprunfile = 'texexec'
+ @@temptexfile = 'texexec.tex'
+
+ def initialize(logger=nil)
+ if @logger = logger then
+ def report(str='')
+ @logger.report(str)
+ end
+ else
+ def report(str='')
+ puts(str)
+ end
+ end
+ @cleanups = Array.new
+ @variables = Hash.new
+ @startuptime = Time.now
+ # options
+ booleanvars.each do |k|
+ setvariable(k,false)
+ end
+ stringvars.each do |k|
+ setvariable(k,'')
+ end
+ standardvars.each do |k|
+ setvariable(k,'standard')
+ end
+ setvariable('distribution', Kpse.distribution)
+ setvariable('texformats', defaulttexformats)
+ setvariable('mpsformats', defaultmpsformats)
+ setvariable('progname', 'context')
+ setvariable('interface', 'standard')
+ setvariable('engine', 'standard') # replaced by tex/mpsengine
+ setvariable('backend', 'pdftex')
+ setvariable('runs', '8')
+ setvariable('randomseed', rand(1440).to_s)
+ # files
+ setvariable('files', [])
+ # defaults
+ setvariable('texengine', 'standard')
+ setvariable('mpsengine', 'standard')
+ setvariable('backend', 'standard')
+ end
+
+ def runtime
+ Time.now - @startuptime
+ end
+
+ def reportruntime
+ report("runtime: #{runtime}")
+ end
+
+ def inspect(name=nil)
+ if ! name || name.empty? then
+ name = [booleanvars,stringvars,standardvars,knownvars]
+ end
+ [name].flatten.each do |n|
+ if str = getvariable(n) then
+ unless (str.class == String) && str.empty? then
+ report("option '#{n}' is set to '#{str}'")
+ end
+ end
+ end
+ end
+
+ def tempfilename(suffix='')
+ @@temprunfile + if suffix.empty? then '' else ".#{suffix}" end
+ end
+
+ def cleanup
+ @cleanups.each do |name|
+ begin
+ File.delete(name) if FileTest.file?(name)
+ rescue
+ report("unable to delete #{name}")
+ end
+ end
+ end
+
+ def cleanuptemprunfiles
+ 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
+ end
+ end
+ rescue
+ end
+ end
+
+ def backends() @@backends.keys.sort end
+
+ def texengines() @@texengines.keys.sort end
+ def mpsengines() @@mpsengines.keys.sort end
+ def texformats() @@texformats.keys.sort end
+ def mpsformats() @@mpsformats.keys.sort end
+
+ def defaulttexformats() ['en','nl','mptopdf'] end
+ def defaultmpsformats() ['metafun'] end
+
+ def texmakeextras(format) @@texmakestr[format] || '' end
+ def mpsmakeextras(format) @@mpsmakestr[format] || '' end
+ def texprocextras(format) @@texprocstr[format] || '' end
+ def mpsprocextras(format) @@mpsprocstr[format] || '' end
+
+ def texmethod(format) @@texmethods[str] || @@texmethods['standard'] end
+ def mpsmethod(format) @@mpsmethods[str] || @@mpsmethods['standard'] end
+
+ def runoptions(engine)
+ if @@runoptions.key?(engine) then @@runoptions[engine].join(' ') else '' end
+ end
+
+ # private
+
+ def cleanuplater(name)
+ begin
+ @cleanups.push(File.expand_path(name))
+ rescue
+ @cleanups.push(name)
+ end
+ end
+
+ def openedfile(name)
+ begin
+ f = File.open(name,'w')
+ rescue
+ report("file '#{File.expand_path(name)}' cannot be opened for writing")
+ return nil
+ else
+ cleanuplater(name) if f
+ return f
+ end
+ end
+
+ def prefixed(format,engine)
+ case engine
+ when /etex|eetex|pdfetex|pdfeetex|pdfxtex|xpdfetex|eomega|aleph|xetex/io then
+ "*#{format}"
+ else
+ format
+ end
+ end
+
+ def quoted(str)
+ if str =~ /^[^\"].* / then "\"#{str}\"" else str end
+ end
+
+ def getarrayvariable(str='')
+ str = getvariable(str)
+ 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 validtexmethod(str) [validsomething(str,@@texmethods)].flatten.first end
+ def validmpsmethod(str) [validsomething(str,@@mpsmethods)].flatten.first end
+
+ def validsomething(str,something)
+ if str then
+ list = [str].flatten.collect do |s|
+ something[s]
+ end .compact.uniq
+ if list.length>0 then
+ if str.class == String then list.first else list end
+ else
+ false
+ end
+ else
+ false
+ end
+ end
+
+ def validbackend(str)
+ if str && @@backends.key?(str) then
+ @@backends[str]
+ else
+ @@backends['standard']
+ end
+ end
+
+ def validprogname(str,engine='standard')
+ if str && @@prognames.key?(str) then
+ @@prognames[str]
+ elsif (engine != 'standard') && @@prognames.key?(engine) then
+ @@prognames[engine]
+ else
+ str
+ end
+ end
+
+ # we no longer support the & syntax
+
+ def formatflag(engine=nil,format=nil)
+ case getvariable('distribution')
+ when 'standard' then prefix = "--fmt"
+ when /web2c/io then prefix = web2cformatflag(engine)
+ when /miktex/io then prefix = "--undump"
+ else return ""
+ end
+ if format then
+ # if engine then
+ # "#{prefix}=#{engine}/#{format}"
+ # else
+ "#{prefix}=#{format}"
+ # end
+ else
+ prefix
+ end
+ end
+
+ def web2cformatflag(engine=nil)
+ # funny that we've standardized on the fmt suffix (at the cost of
+ # 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"
+ end
+ else
+ "--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"
+ else return ""
+ end
+ if progname then
+ if progname = validprogname(progname) then
+ "#{prefix}=#{progname}"
+ else
+ ""
+ end
+ else
+ prefix
+ end
+ end
+
+ def iniflag() # should go to kpse and kpse should become texenv
+ if Kpse.miktex? then
+ "-initialize"
+ else
+ "--ini"
+ end
+ end
+ def tcxflag(file="natural.tcx")
+ if Kpse.miktex? then
+ "-tcx=#{file}"
+ else
+ "--translate-file=#{file}"
+ end
+ end
+
+ def filestate(file)
+ File.mtime(file).strftime("%d/%m/%Y %H:%M:%S")
+ end
+
+ # will go to context/process context/listing etc
+
+ def contextversion # ook elders gebruiken
+ filename = Kpse.found('context.tex')
+ version = 'unknown'
+ begin
+ if FileTest.file?(filename) && IO.read(filename).match(/\\contextversion\{(\d+\.\d+\.\d+)\}/) then
+ version = $1
+ end
+ rescue
+ end
+ return version
+ end
+
+ def makeformats
+ if getvariable('fast') then
+ report('using existing database')
+ else
+ report('updating file database')
+ Kpse.update
+ end
+ # goody
+ if getvariable('texformats') == 'standard' then
+ setvariable('texformats',[getvariable('interface')]) unless getvariable('interface').empty?
+ end
+ # prepare
+ texformats = validtexformat(getarrayvariable('texformats'))
+ mpsformats = validmpsformat(getarrayvariable('mpsformats'))
+ texengine = validtexengine(getvariable('texengine'))
+ mpsengine = validmpsengine(getvariable('mpsengine'))
+ # save current path
+ savedpath = Dir.getwd
+ # generate tex formats
+ 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)
+ end
+ else
+ texformatpath = ''
+ end
+ # generate mps formats
+ if mpsformats && mpsengine && (progname = validprogname(getvariable('progname'),mpsengine)) then
+ 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)
+ end
+ else
+ mpsformatpath = ''
+ end
+ # check for problems
+ report("tex engine path: #{texformatpath}") unless texformatpath.empty?
+ report("mps engine path: #{mpsformatpath}") unless mpsformatpath.empty?
+ [['fmt','tex'],['mem','mps']].each do |f|
+ [[texformatpath,'global'],[mpsformatpath,'global'],[savedpath,'current']].each do |p|
+ begin
+ Dir.chdir(p[0])
+ rescue
+ else
+ Dir.glob("*.#{f[0]}").each do |file|
+ report("#{f[1]}format: #{filestate(file)} > #{File.expand_path(file)}")
+ end
+ end
+ end
+ end
+ # to be sure, go back to current path
+ begin
+ Dir.chdir(savedpath)
+ rescue
+ end
+ # finalize
+ cleanup
+ reportruntime
+ end
+
+ def checkcontext
+
+ # todo : report texmf.cnf en problems
+
+ # basics
+ report("current distribution: #{Kpse.distribution}")
+ report("context source date: #{contextversion}")
+ formatpaths = Kpse.formatpaths
+ globpattern = "**/{#{formatpaths.join(',')}}/*/*.{fmt,efmt,ofmt,xfmt,mem}"
+ report("format path: #{formatpaths.join(' ')}")
+ # utilities
+ report('start of analysis')
+ results = Array.new
+ ['texexec','texutil','ctxtools'].each do |program|
+ result = `texmfstart #{program} --help`
+ result.sub!(/.*?(#{program}[^\n]+)\n.*/mi) do $1 end
+ results.push("#{result}")
+ end
+ # formats
+ cleanuptemprunfiles
+ if formats = Dir.glob(globpattern) then
+ formats.sort.each do |name|
+ cleanuptemprunfiles
+ if f = open(tempfilename('tex'),'w') then
+ # kind of aleph-run-out-of-par safe
+ f << "\\starttext\n"
+ f << " \\relax test \\relax\n"
+ f << "\\stoptext\n"
+ f << "\\endinput\n"
+ f.close
+ if FileTest.file?(tempfilename('tex')) then
+ format = File.basename(name)
+ engine = if name =~ /(pdfetex|aleph|xetex)[\/\\]#{format}/ then $1 else '' end
+ if engine.empty? then
+ engineflag = ""
+ else
+ engineflag = "--engine=#{$1}"
+ end
+ case format
+ when /cont\-([a-z]+)/ then
+ interface = $1.sub(/cont\-/,'')
+ results.push('')
+ results.push("testing interface #{interface}")
+ flags = ['--process','--batch','--once',"--interface=#{interface}",engineflag]
+ # result = Kpse.pipescript('newtexexec',tempfilename,flags)
+ result = runtexexec([tempfilename], flags, 1)
+ if FileTest.file?("#{@@temprunfile}.log") then
+ logdata = IO.read("#{@@temprunfile}.log")
+ if logdata =~ /^\s*This is (.*?)[\s\,]+(.*?)$/mois then
+ if validtexengine($1.downcase) then
+ results.push("#{$1} #{$2.gsub(/\(format.*$/,'')}".strip)
+ end
+ end
+ if logdata =~ /^\s*(ConTeXt)\s+(.*int:\s+[a-z]+.*?)\s*$/mois then
+ results.push("#{$1} #{$2}".gsub(/\s+/,' ').strip)
+ end
+ else
+ results.push("format #{format} does not work")
+ end
+ when /metafun/ then
+ # todo
+ when /mptopdf/ then
+ # todo
+ end
+ else
+ results.push("error in creating #{tempfilename('tex')}")
+ end
+ end
+ cleanuptemprunfiles
+ end
+ end
+ report('end of analysis')
+ report
+ results.each do |line|
+ report(line)
+ end
+ cleanuptemprunfiles
+
+ end
+
+ private
+
+ def makeuserfile
+ language = getvariable('language')
+ mainlanguage = getvariable('mainlanguage')
+ bodyfont = getvariable('bodyfont')
+ if f = openedfile("cont-fmt.tex") then
+ f << "\\unprotect"
+ case language
+ when 'all' then
+ f << "\\preloadallpatterns\n"
+ when '' then
+ f << "% no language presets\n"
+ when 'standard'
+ f << "% using defaults\n"
+ else
+ languages = language.split(',')
+ languages.each do |l|
+ f << "\\installlanguage[\\s!#{l}][\\c!state=\\v!start]\n"
+ end
+ mainlanguage = languages.first
+ end
+ unless mainlanguage == 'standard' then
+ f << "\\setupcurrentlanguage[\\s!#{mainlanguage}]\n";
+ end
+ unless bodyfont == 'standard' then
+ # ~ will become obsolete when lmr is used
+ f << "\\definetypescriptsynonym[cmr][#{bodyfont}]"
+ # ~ is already obsolete for some years now
+ f << "\\definefilesynonym[font-cmr][font-#{bodyfont}]\n"
+ end
+ f << "\\protect\n"
+ f << "\\endinput\n"
+ f.close
+ end
+ end
+
+ def makeresponsefile
+ interface = getvariable('interface')
+ if f = openedfile("mult-def.tex") then
+ case interface
+ when 'standard' then
+ f << "% using default response interface"
+ else
+ f << "\\def\\currentresponses\{#{interface}\}\n"
+ end
+ f << "\\endinput\n"
+ f.close
+ end
+ end
+
+ private # will become baee/context
+
+ @@preamblekeys = [
+ ['tex','texengine'],
+ ['program','texengine'],
+ ['translate','tcxfilter'],
+ ['tcx','tcxfilter'],
+ ['output','backend'],
+ ['mode','mode'],
+ ['ctx','ctxfile'],
+ ['version','contextversion'],
+ ['format','texformat'],
+ ['interface','texformat']
+ ]
+
+ def scantexpreamble(filename)
+ begin
+ if FileTest.file?(filename) and tex = File.open(filename) then
+ while str = tex.gets and str.chomp! do
+ if str =~ /^\%\s*(.*)/o then
+ vars = Hash.new
+ $1.split(/\s+/o).each do |s|
+ k, v = s.split('=')
+ vars[k] = v
+ end
+ @@preamblekeys.each do |v|
+ setvariable(v[1],vars[v[0]]) if vars.key?(v[0])
+ end
+ else
+ break
+ end
+ end
+ tex.close
+ end
+ rescue
+ # well, let's not worry too much
+ end
+ end
+
+ def scantexcontent(filename)
+ 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
+ when /\\(stelle|verwende|umgebung|benutze)/o then
+ setvariable('texformat','de') ; break
+ when /\\(stel|gebruik|omgeving)/o then
+ setvariable('texformat','nl') ; break
+ when /\\(use|setup|environment)/o then
+ setvariable('texformat','en') ; break
+ when /\\(usa|imposta|ambiente)/o then
+ setvariable('texformat','it') ; break
+ when /(height|width|style)=/o then
+ setvariable('texformat','en') ; break
+ when /(hoehe|breite|schrift)=/o then
+ setvariable('texformat','de') ; break
+ when /(hoogte|breedte|letter)=/o then
+ setvariable('texformat','nl') ; break
+ when /(altezza|ampiezza|stile)=/o then
+ setvariable('texformat','it') ; break
+ when /externfiguur/o then
+ setvariable('texformat','nl') ; break
+ when /externalfigure/o then
+ setvariable('texformat','en') ; break
+ when /externeabbildung/o then
+ setvariable('texformat','de') ; break
+ when /figuraesterna/o then
+ setvariable('texformat','it') ; break
+ end
+ end
+ tex.close
+ end
+
+ end
+
+ private # will become base/context
+
+ def pushresult(filename,resultname)
+ fname = File.unsuffixed(filename)
+ rname = File.unsuffixed(resultname)
+ if ! rname.empty? && (rname != fname) then
+ report("outputfile #{rname}")
+ ['tuo','log','dvi','pdf'].each do |s|
+ File.silentrename(File.suffixed(fname,s),File.suffixed('texexec',s))
+ end
+ ['tuo'].each do |s|
+ File.silentrename(File.suffixed(rname,s),File.suffixed(fname,s)) if FileTest.file?(File.suffixed(rname,s))
+ end
+ end
+ end
+
+ def popresult(filename,resultname)
+ fname = File.unsuffixed(filename)
+ rname = File.unsuffixed(resultname)
+ if ! rname.empty? && (rname != fname) then
+ report("renaming #{fname} to #{rname}")
+ ['tuo','log','dvi','pdf'].each do |s|
+ File.silentrename(File.suffixed(fname,s),File.suffixed(rname,s))
+ end
+ report("restoring #{fname}")
+ unless $fname == 'texexec' then
+ ['tuo','log','dvi','pdf'].each do |s|
+ File.silentrename(File.suffixed('texexec',s),File.suffixed(fname,s))
+ end
+ end
+ end
+ end
+
+ def makestubfile(rawname,forcexml=false)
+ if tmp = File.open(File.suffixed(rawname,'run'),'w') 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 << "\\processXMLfilegrouped{#{rawname}}\n"
+ else
+ tmp << "\\processfile{#{rawname}}\n"
+ end
+ tmp << "\\stoptext\n"
+ tmp.close
+ return "run"
+ else
+ return File.splitname(rawname)[1]
+ end
+ end
+
+end
+
+class TEX
+
+ 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
+ end
+ reportruntime
+ end
+
+ def processmptex
+ getarrayvariable('files').each do |filename|
+ setvariable('filename',filename)
+ report("processing graphic '#{filename}'")
+ runtexmp(filename)
+ end
+ reportruntime
+ end
+
+ def processmpxtex
+ getarrayvariable('files').each do |filename|
+ setvariable('filename',filename)
+ report("processing text of graphic '#{filename}'")
+ processmpx(filename,true)
+ end
+ reportruntime
+ end
+
+ def deleteoptionfile(rawname)
+ begin
+ File.delete(File.suffixed(rawname,'top'))
+ rescue
+ 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"
+ 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"]
+ 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"
+ 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
+ end
+ else
+ pagelist << page
+ end
+ end
+ opt << "\\def\\pagestoshipout\{pagelist.join(',')\}\n";
+ end
+ 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
+ end
+ end
+
+ def takeprecautions
+ ENV['MPXCOMAND'] = '0' # else loop
+ if getvariable('paranoid') then
+ ENV['SHELL_ESCAPE'] = ENV['SHELL_ESCAPE'] || 'f'
+ ENV['OPENOUT_ANY'] = ENV['OPENOUT_ANY'] || 'p'
+ ENV['OPENIN_ANY'] = ENV['OPENIN_ANY'] || 'p'
+ elsif getvariable('notparanoid') then
+ ENV['SHELL_ESCAPE'] = ENV['SHELL_ESCAPE'] || 't'
+ ENV['OPENOUT_ANY'] = ENV['OPENOUT_ANY'] || 'a'
+ ENV['OPENIN_ANY'] = ENV['OPENIN_ANY'] || 'a'
+ end
+ if ENV['OPENIN_ANY'] && (ENV['OPENIN_ANY'] == 'p') then # first test redundant
+ setvariable('paranoid', true)
+ end
+ if ENV.key?('SHELL_ESCAPE') && (ENV['SHELL_ESCAPE'] == 'f') then
+ setvariable('automprun',true)
+ end
+ ['TXRESOURCES','MPRESOURCES','MFRESOURCES'].each do |res|
+ [getvariable('runpath'),getvariable('path')].each do |pat|
+ unless pat.empty? then
+ if ENV.key?(res) then
+ ENV[res] = if ENV[res].empty? then pat else pat + ":" + ENV[res] end
+ else
+ ENV[res] = pat
+ end
+ end
+ end
+ end
+ end
+
+ def runtex(filename)
+ texengine = validtexengine(getvariable('texengine'))
+ texformat = validtexformat(getarrayvariable('texformats').first)
+ progname = validprogname(getvariable('progname'))
+ report("tex engine: #{texengine}")
+ 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)
+ else
+ false
+ end
+ end
+
+ def runmp(filename)
+ 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)
+ else
+ false
+ end
+ end
+
+ def runtexmp(filename,filetype='')
+ mpfile = File.suffixed(filename,filetype,'mp')
+ if File.atleast?(mpfile,25) then
+ # first run needed
+ File.silentdelete(File.suffixed(mpfile,'mpt'))
+ doruntexmp(mpfile,false)
+ mpgraphics = checkmpgraphics(mpfile)
+ mplabels = checkmplabels(mpfile)
+ if mpgraphics || mplabels then
+ # second run needed
+ doruntexmp(mpfile,mplabels)
+ end
+ end
+ end
+
+ def runtexmpjob(filename,filetype='')
+ mpfile = File.suffixed(filename,filetype,'mp')
+ if File.atleast?(mpfile,25) && (data = File.silentread(mpfile)) 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
+ options = Array.new
+ options.push("--mptex")
+ options.push("--nomp")
+ options.push("--mpyforce") if getvariable('forcempy') || getvariable('mpyforce')
+ 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)
+ end
+ end
+ return false
+ end
+
+ def runtexutil(filename=[], options=['--ref','--ij','--high'], old=false)
+ filename.each do |fname|
+ if old then
+ Kpse.runscript('texutil',fname,options)
+ else
+ begin
+ logger = Logger.new('TeXUtil')
+ if tu = TeXUtil::Converter.new(logger) and tu.loaded(fname) then
+ tu.saved if tu.processed
+ end
+ rescue
+ Kpse.runscript('texutil',fname,options)
+ end
+ end
+ end
+ end
+
+ # 1=tex 2=mptex 3=mpxtex
+
+ 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)
+ end
+ end
+ job.setvariable("files",filename)
+ case mode
+ when 1 then job.processtex
+ when 2 then job.processmptex
+ when 3 then job.processmpxtex
+ end
+ job.inspect && Kpse.inspect if getvariable('verbose')
+ return true
+ else
+ Kpse.runscript('texexec',filename,options)
+ end
+ rescue
+ Kpse.runscript('texexec',filename,options)
+ end
+ end
+
+ def fixbackendvars(backend)
+ ENV['backend'] = backend ;
+ ENV['progname'] = backend unless validtexengine(backend)
+ ENV['TEXFONTMAPS'] = ".;\$TEXMF/fonts/map/{#{backend},pdftex,dvips,}//"
+ 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
+ end
+ rescue
+ mapfiles = ''
+ end
+ system("dvips #{mapfiles} #{File.unsuffixed(rawname)}")
+ when 'pdftex' then
+ # no need for postprocessing
+ else
+ report("no postprocessing needed")
+ end
+ end
+
+ def processfile
+
+ takeprecautions
+
+ rawname = getvariable('filename')
+
+ jobname = getvariable('filename')
+ suffix = getvariable('suffix')
+ result = getvariable('result')
+
+ runonce = getvariable('once')
+ finalrun = getvariable('final') || (getvariable('arrange') && ! getvariable('noarrange'))
+ globalfile = getvariable('globalfile')
+
+ if getvariable('autopath') then
+ jobname = File.basename(jobname)
+ inppath = File.dirname(jobname)
+ else
+ inppath = ''
+ end
+
+ jobname, jobsuffix = File.splitname(jobname,'tex')
+
+ jobname = File.unixfied(jobname)
+ inppath = File.unixfied(inppath)
+ result = File.unixfied(result)
+
+ orisuffix = jobsuffix # still needed ?
+
+ setvariable('nomprun',true) if orisuffix == 'mpx' # else cylic run
+
+ PDFview.closeall if getvariable('autopdf')
+
+ forcexml = jobsuffix.match(/^(xml|fo|fox|rlg|exa)$/io) # nil or match
+
+ dummyfile = false
+
+ # fuzzy code snippet: (we kunnen kpse: prefix gebruiken)
+
+ unless FileTest.file?(File.suffixed(jobname,jobsuffix)) then
+ if FileTest.file?(rawname + '.tex') then
+ jobname = rawname.dup
+ jobsuffix = 'tex'
+ end
+ end
+
+ # we can have funny names, like 2005.10.10 (given without suffix)
+
+ rawname = jobname + '.' + jobsuffix
+
+ unless FileTest.file?(rawname) then
+ inppath.split(',').each do |ip|
+ break if dummyfile = FileTest.file?(File.join(ip,rawname))
+ end
+ 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'))
+
+ envs = ctx.environments
+ mods = ctx.modules
+
+ # merge environment and module specs
+
+ envs << getvariable('environments') unless getvariable('environments').empty?
+ mods << getvariable('modules') unless getvariable('modules') .empty?
+
+ envs = envs.uniq.join(',')
+ mods = mods.uniq.join(',')
+
+ report("using environments #{envs}") if envs.length > 0
+ report("using modules #{mods}") if mods.length > 0
+
+ setvariable('environments', envs)
+ setvariable('modules', mods)
+
+ # 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)
+
+ method = validtexmethod(validtexformat(getvariable('texformats')))
+
+ report("tex processing method: #{method}")
+
+ case method
+
+ when 'context' then
+ if getvariable('simplerun') || runonce then
+ makeoptionfile(rawname,jobname,orisuffix,true,true,3) unless getvariable('nooptionfile')
+ ok = runtex(rawname)
+ if ok then
+ ok = runtexutil(rawname) if getvariable('texutil') || getvariable('forcetexutil')
+ runbackend(rawname)
+ popresult(rawname,result)
+ 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))
+ end
+ if getvariable('automprun') then # check this
+ ['mprun','mpgraph'].each do |s|
+ state.register(File.suffixed(rawname,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')
+ end
+ ok = runtex(File.suffixed(rawname,jobsuffix))
+ if ok && (nofruns > 1) then
+ unless getvariable('nompmode') then
+ mprundone = runtexmpjob(rawname, "mpgraph")
+ mprundone = runtexmpjob(rawname, "mprun")
+ end
+ ok = runtexutil(rawname)
+ state.update
+ stoprunning = state.stable?
+ end
+ end
+ ok = runtexutil(rawname) if (nofruns == 1) && getvariable('texutil')
+ if ok && finalrun && (nofruns > 1) then
+ makeoptionfile(rawname,jobname,orisuffix,true,finalrun,4) unless getvariable('nooptionfile')
+ report("final TeX run #{texruns}")
+ ok = runtex(File.suffixed(rawname,jobsuffix))
+ end
+ ['tmp','top'].each do |s| # previous tuo file / runtime option file
+ File.silentdelete(File.suffixed(rawname,s))
+ end
+ File.silentrename(File.suffixed(rawname,'top'),File.suffixed(rawname,'tmp'))
+ if ok then
+ runbackend(rawname)
+ popresult(rawname,result)
+ end
+ end
+
+ Kpse.runscript('ctxtools',rawname,'--purge') if getvariable('purge')
+ Kpse.runscript('ctxtools',rawname,'--purgeall') if getvariable('purgeall')
+
+ when 'latex' then
+
+ ok = runtex(rawname)
+
+ else
+
+ ok = runtex(rawname)
+
+ end
+
+ if (dummyfile or forcexml) and FileTest.file?(rawname) then
+ begin
+ File.delete(File.suffixed(rawname,'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'))
+ end
+
+ end
+
+ end
+
+ # mp specific
+
+ def doruntexmp(mpname,mergebe=true,context=true)
+ texfound = false
+ mpbetex = Hash.new
+ mpfile = File.suffixed(mpname,'mp')
+ mpcopy = File.suffixed(mpname,'copy','mp')
+ setvariable('mp.file',mpfile)
+ setvariable('mp.line','')
+ setvariable('mp.error','')
+ if mpdata = File.silentread(mpfile) 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
+ if mergebe then
+ mpdata.gsub!(/beginfig\s*\((\d+)\)\s*\;(.*?)endfig\s*\;/o) do
+ n, str = $1, $2
+ if str =~ /(.*?)(verbatimtex.*?etex)\s*\;(.*)/o then
+ "beginfig(#{n})\;\n$1$2\;\n#{mpbetex(n)}\n$3\;endfig\;\n"
+ else
+ "beginfig(#{n})\;\n#{mpbetex(n)}\n#{str}\;endfig\;\n"
+ end
+ end
+ end
+ unless mpdata =~ /beginfig\s*\(\s*0\s*\)/o then
+ mp << mpbetex[0] if mpbetex.key?(0)
+ end
+ mp << mpdata # ??
+ mp << "\n"
+ mp << "end"
+ mp << "\n"
+ mp.close
+ end
+ processmpx(mpname) if texfound
+ if getvariable('batchmode') then
+ options = ' --interaction=batch'
+ elsif getvariable('nonstopmode') then
+ options = ' --interaction=nonstop'
+ else
+ options = ''
+ end
+ # todo plain|mpost|metafun
+ ok = runmp(mpname)
+ if f = File.silentopen(File.suffixed(mpfile,'log')) then
+ while str = f.gets do
+ if str =~ /^l\.(\d+)\s(.*?)\n/o then
+ setvariable('mp.line',$1)
+ setvariable('mp.error',$2)
+ break
+ end
+ end
+ f.close
+ end
+ File.silentrename(mpfile,"mptrace.tmp")
+ File.silentrename(mpcopy, mpfile)
+ end
+ end
+
+ def processmpx(mpname,context=true)
+ mpname = File.suffixed(mpname,'mp')
+ if File.atleast?(mpname,10) && (data = File.silentread(mpname)) 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
+ if context then
+ ok = RunConTeXtFile(mptex)
+ else
+ ok = RunSomeTeXFile(mptex)
+ end
+ ok = ok && FileTest.file?(mpdvi) && system("dvitomp #{mpdvi} #{mpmpx}")
+ [mptex,mpdvi,mplog].each do |mpfil|
+ File.silentdelete(mpfil)
+ end
+ end
+ end
+ rescue
+ # error in processing mpx file
+ end
+ end
+ end
+
+ def checkmpgraphics(mpname)
+ mpoptions = ''
+ if getvariable('makempy') then
+ mpoptions += " --makempy "
+ end
+ if getvariable('mpyforce') || getvariable('forcempy') then
+ mpoptions += " --force "
+ else
+ mponame = File.suffixed(mpname,'mpo')
+ mpyname = File.suffixed(mpname,'mpy')
+ return false unless File.atleast?(mponame,32)
+ mpochecksum = State.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
+ str = f.gets.chomp
+ f.close
+ if str =~ /^\%\s*mpochecksum\s*\:\s*(\d+)/o then
+ return false if mpochecksum == $1
+ end
+ end
+ end
+ return Kpse.runscript('makempy',mpname)
+ end
+
+ def checkmplabels(mpname)
+ mpname = File.suffixed(mpname,'mpt')
+ if File.atleast?(mpname,10) && (mp = File.open(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
+ unless t.empty? then
+ labels[$1] += "#{t}\n"
+ t = ''
+ end
+ labels[$1] += "$2\n"
+ end
+ end
+ mp.close
+ return labels if labels.size>0
+ end
+ return nil
+ end
+
+end