From dddd4cf24fcf8ef5f9c76acb7da468f502cd0bcd Mon Sep 17 00:00:00 2001 From: Hans Hagen Date: Tue, 21 Jun 2005 00:00:00 +0200 Subject: stable 2005.06.21 --- scripts/context/perl/texexec.pl | 129 ++++-- scripts/context/ruby/base/file.rb | 6 +- scripts/context/ruby/base/kpse.rb | 6 +- scripts/context/ruby/base/tex.rb | 513 ++++++++++++--------- scripts/context/ruby/base/texutil.rb | 790 +++++++++++++++++++++++++++++++++ scripts/context/ruby/base/variables.rb | 8 + scripts/context/ruby/ctxtools.rb | 82 +++- scripts/context/ruby/newtexexec.rb | 35 +- scripts/context/ruby/newtexutil.rb | 601 +------------------------ scripts/context/ruby/texmfstart.rb | 2 +- 10 files changed, 1289 insertions(+), 883 deletions(-) create mode 100644 scripts/context/ruby/base/texutil.rb (limited to 'scripts') diff --git a/scripts/context/perl/texexec.pl b/scripts/context/perl/texexec.pl index 263388a4c..9a8f2bff0 100644 --- a/scripts/context/perl/texexec.pl +++ b/scripts/context/perl/texexec.pl @@ -155,6 +155,7 @@ my $ProducePdfT = 0; my $ProducePdfM = 0; my $ProducePdfX = 0; my $ProducePdfXTX = 0; +my $ProducePs = 0; my $Input = ""; my $Result = ''; my $Suffix = ''; @@ -263,6 +264,7 @@ my $MakeMpy = ''; "pdx" => \$ProducePdfX, "dpx" => \$ProducePdfX, "xtx" => \$ProducePdfXTX, + "ps" => \$ProducePs, "pdfarrange" => \$PdfArrange, "pdfselect" => \$PdfSelect, "pdfcombine" => \$PdfCombine, @@ -380,6 +382,7 @@ if ( $DoMPTeX || $DoMPXTeX ) { $ProducePdfX = 0; $ProducePdfM = 0; $ProducePdfXTX = 0; + $ProducePs = 0; } if ( $PdfArrange || $PdfSelect || $PdfCopy || $PdfTrim || $PdfCombine ) { @@ -391,6 +394,7 @@ if ($ProducePdfT) { $OutputFormat = "pdftex" } elsif ($ProducePdfM) { $OutputFormat = "dvipdfm" } elsif ($ProducePdfX) { $OutputFormat = "dvipdfmx" } elsif ($ProducePdfXTX) { $OutputFormat = "xetex" } +elsif ($ProducePs) { $OutputFormat = "dvips" } if ( $ProducePdfXTX ) { $TeXProgram = 'xetex' ; # ignore the default pdfetex engine @@ -884,6 +888,7 @@ $OutputFormats{pdftex} = "pdftex"; $OutputFormats{pdf} = "pdftex"; $OutputFormats{dvipdfm} = "dvipdfm"; $OutputFormats{dpm} = "dvipdfm"; $OutputFormats{dvipdfmx} = "dvipdfmx"; $OutputFormats{dpx} = "dvipdfmx"; $OutputFormats{xetex} = "xetex"; $OutputFormats{xtx} = "xetex"; +$OutputFormats{dvips} = "dvips"; $OutputFormats{ps} = "dvips"; # kind of obsolete now that yandy is gone @@ -1405,6 +1410,7 @@ sub ScanTeXPreamble { $ProducePdfM = ($OutputFormat eq "dvipdfm") ; $ProducePdfX = ($OutputFormat eq "dvipdfmx") ; $ProducePdfXTX = ($OutputFormat eq "xetex") ; + $ProducePs = ($OutputFormat eq "dvips") ; } sub ScanContent { @@ -1480,14 +1486,17 @@ sub PrepRunTeX { return $cmd; } +my $emergencyend = "" ; +#~ my $emergencyend = "\\emergencyend" ; + sub RunTeX { my ( $JobName, $JobSuffix ) = @_; my $StartTime = time; my $cmd = PrepRunTeX($JobName, $JobSuffix, ''); if ($EnterBatchMode) { - $Problems = System("$cmd"); + $Problems = System("$cmd $emergencyend"); } else { - $Problems = System("$cmd"); + $Problems = System("$cmd $emergencyend"); } my $StopTime = time - $StartTime; print "\n return code : $Problems"; @@ -1729,7 +1738,7 @@ sub RunConTeXtFile { } elsif (/\<\?context\-directive\s+(.+?)\s+(.+?)\s+(.+?)\s*\?\>/o) { my ($class, $key, $value) = ($1, $2, $3) ; if ($class eq 'job') { - if ($key eq 'stylefile') { + if (($key eq 'stylefile') || ($key eq 'environment')) { print TMP "\\environment $value\n" ; } elsif ($key eq 'module') { print TMP "\\usemodule[$value]\n" ; @@ -1838,7 +1847,7 @@ sub RunConTeXtFile { $tubchecksumafter = CheckTubChanges($JobName) ; if ($AutoMPRun) { $mpchecksumafter = CheckMPChanges($JobName) } if ( ( !$Problems ) && ( $NOfRuns > 1 ) ) { - if ( !$NoMPMode ) { + unless ( $NoMPMode ) { $MPrundone = RunTeXMP( $JobName, "mpgraph" ); $MPrundone = RunTeXMP( $JobName, "mprun" ); } @@ -1879,6 +1888,21 @@ sub RunConTeXtFile { $ENV{'backend'} = $ENV{'progname'} = 'xetex' ; $ENV{'TEXFONTMAPS'} = '.;$TEXMF/fonts/map/{xetex,pdftex,dvips,}//' ; System("xdv2pdf $JobName.xdv") ; + } elsif ($ProducePs) { + $ENV{'backend'} = $ENV{'progname'} = 'dvips' ; + $ENV{'TEXFONTMAPS'} = '.;$TEXMF/fonts/map/{dvips,pdftex,}//' ; + # temp hack, some day there will be map file loading in specials + my $mapfiles = '' ; + if (-f "$JobName.tui") { + open(TUI,"$JobName.tui") ; + while () { + if (/c \\usedmapfile\{.\}\{(.*?)\}/o) { + $mapfiles .= "-u +$1 " ; + } + } + close(TUI) ; + } + System("dvips $mapfiles $JobName.dvi") ; } PopResult($JobName); } @@ -1938,6 +1962,50 @@ sub RunModule { # the next one can be more efficient: directly process ted # file a la --use=abr-01,mod-01 +sub checktexformatpath { + # engine support is either broken of not implemented in some + # distributions, so we need to take care of it ourselves + my $texformats ; + if (defined($ENV{'TEXFORMATS'})) { + $texformats = $ENV{'TEXFORMATS'} ; + } else { + $texformats = '' ; + } + if ($texformats eq '') { + if ($UseEnginePath) { + if ($dosish) { + $texformats = `kpsewhich --engine=$TeXExecutable --expand-var=\$TEXFORMATS` ; + } else { + $texformats = `kpsewhich --engine=$TeXExecutable --expand-var=\\\$TEXFORMATS` ; + } + } else { + if ($dosish) { + $texformats = `kpsewhich --expand-var=\$TEXFORMATS` ; + } else { + $texformats = `kpsewhich --expand-var=\\\$TEXFORMATS` ; + } + } + chomp($texformats) ; + } + if (($texformats !~ /web2c\/.*$TeXExecutable/) && ($texformats !~ /web2c[\/\\].*\$engine/i)) { + $texformats =~ s/(web2c\/\{)(\,\})/$1\$engine$2/ ; # needed for empty engine flags + if ($texformats !~ /web2c[\/\\].*\$ENGINE/) { + $texformats =~ s/web2c/web2c\/{\$engine,}/ ; # needed for me + } + $ENV{'TEXFORMATS'} = $texformats ; + print " fixing texformat path : $ENV{'TEXFORMATS'}\n"; + } else { + print " using texformat path : $ENV{'TEXFORMATS'}\n" if ($Verbose) ; + } + if (! defined($ENV{'ENGINE'})) { + if ($MpEngineSupport) { + $ENV{'ENGINE'} .= $MpExecutable ; + } ; + $ENV{'ENGINE'} = $TeXExecutable ; + print "fixing engine variable : $ENV{'ENGINE'}\n"; + } +} + sub DoRunModule { my ( $FileName, $FileSuffix ) = @_; RunPerlScript( $TeXUtil, "--documents $FileName.$FileSuffix" ); @@ -1959,8 +2027,8 @@ sub DoRunModule { print MOD "\\readlocfile{$FileName.ted}{}{}\n"; print MOD "\\stoptext\n"; close(MOD); + checktexformatpath ; RunConTeXtFile( $ModuleFile, "tex" ); - if ( $FileName ne $ModuleFile ) { foreach my $FileSuffix ( "dvi", "pdf", "tui", "tuo", "log" ) { unlink("$FileName.$FileSuffix"); @@ -1998,6 +2066,7 @@ sub RunFigures { print FIG "\\stoptext\n"; close(FIG); $ConTeXtInterface = "en"; + checktexformatpath ; RunConTeXtFile( $FiguresFile, "tex" ); unlink('texutil.tuf') if ( -f 'texutil.tuf' ); } @@ -2038,6 +2107,7 @@ sub RunListing { print LIS "\\stoptext\n"; close(LIS); $ConTeXtInterface = "en"; + checktexformatpath ; RunConTeXtFile( $ListingFile, "tex" ); } @@ -2083,6 +2153,7 @@ sub RunArrange { print ARR "\\stoptext\n"; close(ARR); $ConTeXtInterface = "en"; + checktexformatpath ; RunConTeXtFile( $ModuleFile, "tex" ); } @@ -2131,6 +2202,7 @@ sub RunSelect { print SEL "\\stoptext\n"; close(SEL); $ConTeXtInterface = "en"; + checktexformatpath ; RunConTeXtFile( $SelectFile, "tex" ); } @@ -2181,6 +2253,7 @@ sub RunCopy { print COP "\\stoptext\n"; close(COP); $ConTeXtInterface = "en"; + checktexformatpath ; RunConTeXtFile( $CopyFile, "tex" ); } @@ -2231,6 +2304,7 @@ sub RunCombine { print COM "\\stoptext\n"; close(COM); $ConTeXtInterface = "en"; + checktexformatpath ; RunConTeXtFile( $CombineFile, "tex" ); } @@ -2432,50 +2506,6 @@ sub RunMpFormat { my $dir = File::Temp::tempdir(CLEANUP=>1) ; my ($fh, $filename) = File::Temp::tempfile(DIR=>$dir, UNLINK=>1); -sub checktexformatpath { - # engine support is either broken of not implemented in some - # distributions, so we need to take care of it ourselves - my $texformats ; - if (defined($ENV{'TEXFORMATS'})) { - $texformats = $ENV{'TEXFORMATS'} ; - } else { - $texformats = '' ; - } - if ($texformats eq '') { - if ($UseEnginePath) { - if ($dosish) { - $texformats = `kpsewhich --engine=$TeXExecutable --expand-var=\$TEXFORMATS` ; - } else { - $texformats = `kpsewhich --engine=$TeXExecutable --expand-var=\\\$TEXFORMATS` ; - } - } else { - if ($dosish) { - $texformats = `kpsewhich --expand-var=\$TEXFORMATS` ; - } else { - $texformats = `kpsewhich --expand-var=\\\$TEXFORMATS` ; - } - } - chomp($texformats) ; - } - if (($texformats !~ /web2c\/.*$TeXExecutable/) && ($texformats !~ /web2c[\/\\].*\$engine/i)) { - $texformats =~ s/(web2c\/\{)(\,\})/$1\$engine$2/ ; # needed for empty engine flags - if ($texformats !~ /web2c[\/\\].*\$ENGINE/) { - $texformats =~ s/web2c/web2c\/{\$engine,}/ ; # needed for me - } - $ENV{'TEXFORMATS'} = $texformats ; - print " fixing texformat path : $ENV{'TEXFORMATS'}\n"; - } else { - print " using texformat path : $ENV{'TEXFORMATS'}\n" if ($Verbose) ; - } - if (! defined($ENV{'ENGINE'})) { - if ($MpEngineSupport) { - $ENV{'ENGINE'} .= $MpExecutable ; - } ; - $ENV{'ENGINE'} = $TeXExecutable ; - print "fixing engine variable : $ENV{'ENGINE'}\n"; - } -} - sub RunFiles { my $currentpath = cwd() ; my $oldrunpath = $RunPath ; @@ -2819,6 +2849,7 @@ sub RunMPX { open( TMP, ">>$MpTex" ); print TMP "\\end\n"; # to be sure close(TMP); + checktexformatpath ; if ( ( $Format eq '' ) || ( $Format =~ /^cont.*/io ) ) { RunConTeXtFile( $MpTmp, "tex" ); } else { diff --git a/scripts/context/ruby/base/file.rb b/scripts/context/ruby/base/file.rb index b7170d555..f6189043c 100644 --- a/scripts/context/ruby/base/file.rb +++ b/scripts/context/ruby/base/file.rb @@ -4,7 +4,11 @@ class File def File.suffixed(name,sufa,sufb=nil) if sufb then - unsuffixed(name) + "-#{sufa}.#{sufb}" + if sufa.empty? then + unsuffixed(name) + ".#{sufb}" + else + unsuffixed(name) + "-#{sufa}.#{sufb}" + end else unsuffixed(name) + ".#{sufa}" end diff --git a/scripts/context/ruby/base/kpse.rb b/scripts/context/ruby/base/kpse.rb index 7073ad017..a5e2ecac2 100644 --- a/scripts/context/ruby/base/kpse.rb +++ b/scripts/context/ruby/base/kpse.rb @@ -284,12 +284,14 @@ module Kpse def Kpse.runscript(name,filename=[],options=[]) setscript(name,`texmfstart --locate #{name}`) unless @@scripts.key?(name) - system("#{@@scripts[name]} #{[options].flatten.join(' ')} #{[filename].flatten.join(' ')}") + cmd = "#{@@scripts[name]} #{[options].flatten.join(' ')} #{[filename].flatten.join(' ')}" + system(cmd) end def Kpse.pipescript(name,filename=[],options=[]) setscript(name,`texmfstart --locate #{name}`) unless @@scripts.key?(name) - `#{@@scripts[name]} #{[options].flatten.join(' ')} #{[filename].flatten.join(' ')}` + cmd = "#{@@scripts[name]} #{[options].flatten.join(' ')} #{[filename].flatten.join(' ')}" + `#{cmd}` end private diff --git a/scripts/context/ruby/base/tex.rb b/scripts/context/ruby/base/tex.rb index cea6662ae..2be0548d3 100644 --- a/scripts/context/ruby/base/tex.rb +++ b/scripts/context/ruby/base/tex.rb @@ -11,6 +11,8 @@ # todo: write systemcall for mpost to file so that it can be run # faster +# report ? + require 'base/variables' require 'base/kpse' require 'base/system' @@ -18,6 +20,30 @@ require 'base/state' require 'base/pdf' require 'base/file' +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 @@ -33,42 +59,65 @@ class TEX @@texformats = Hash.new @@mpsformats = Hash.new @@prognames = Hash.new + @@texmakestr = Hash.new + @@texprocstr = Hash.new + @@mpsmakestr = Hash.new + @@mpsprocstr = 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 + @@texmethods = Hash.new + @@mpsmethods = Hash.new - ['metapost','mpost','standard'] .each do |e| @@mpsengines[e] = 'mpost' end + ['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 - ['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 + ['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 + ['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 + ['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 + ['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', 'fastmode', 'fastdisabled', 'silentmode', 'final', + 'batchmode', 'nonstopmode', 'fast', 'fastdisabled', 'silentmode', 'final', 'paranoid', 'notparanoid', 'nobanner', 'once', 'allpatterrns', 'nompmode', 'nomprun', 'automprun', 'nomapfiles', 'local', @@ -77,7 +126,7 @@ class TEX 'mpyforce', 'forcempy', 'forcetexutil', 'texutil', 'globalfile', 'autopath', - 'purge', 'pdfopen', 'simplerun', + 'purge', 'pdfopen', 'simplerun', 'verbose', ] @@stringvars = [ 'modefile', 'result', 'suffix', 'response', 'path', @@ -120,7 +169,15 @@ class TEX @@temptexfile = 'texexec.tex' def initialize(logger) - @logger = logger + 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 @@ -139,12 +196,16 @@ class TEX setvariable('mpsformats', defaultmpsformats) setvariable('progname', 'context') setvariable('interface', 'standard') - setvariable('engine', 'standard') + setvariable('engine', 'standard') # replaced by tex/mpsengine setvariable('backend', 'pdftex') setvariable('runs', '8') - setvariable('randomseed', rand(1440)) + setvariable('randomseed', rand(1440).to_s) # files - setvariable('files', []) + setvariable('files', []) + # defaults + setvariable('texengine', 'standard') + setvariable('mpsengine', 'standard') + setvariable('backend', 'standard') end def runtime @@ -193,33 +254,23 @@ class TEX end end - def texengines - @@texengines.keys.sort - end + def backends() @@backends.keys.sort end - def mpsengines - @@mpsengines.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 backends - @@backends.keys.sort - end + def defaulttexformats() ['en','nl','mptopdf'] end + def defaultmpsformats() ['metafun'] end - def texformats - @@texformats.keys.sort - 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 mpsformats - @@mpsformats.keys.sort - end - - def defaulttexformats - ['en','nl','mptopdf'] - end - - def defaultmpsformats - ['metafun'] - 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 @@ -265,18 +316,14 @@ 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) 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| @@ -320,11 +367,11 @@ class TEX else return "" end if format then - if engine then - "#{prefix}=#{engine}/#{format}" - else + # if engine then + # "#{prefix}=#{engine}/#{format}" + # else "#{prefix}=#{format}" - end + # end else prefix end @@ -362,12 +409,8 @@ class TEX end end - def iniflag - "--ini" - end - def tcxflag - "--translate-file=natural.tcx" - end + def iniflag() "--ini" end + def tcxflag() "--translate-file=natural.tcx" end def filestate(file) File.mtime(file).strftime("%d/%m/%Y %H:%M:%S") @@ -388,6 +431,12 @@ class TEX 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? @@ -413,14 +462,11 @@ class TEX makeuserfile makeresponsefile end - texformats.each do |format| - if texformat = validtexformat(format) then - report("generating tex format #{texformat}") - # report("some texmf environment variables are fixed") if Kpse.fixtexmfvars(texengine) - command = [quoted(texengine),prognameflag(progname),iniflag,tcxflag,prefixed(texformat,texengine)].join(' ') - report(command) if getvariable('verbose') - system(command) - 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 = '' @@ -434,14 +480,11 @@ class TEX Dir.chdir(mpsformatpath) rescue end - mpsformats.each do |format| - if mpsformat = validmpsformat(format) then - report("generating mps format #{mpsformat}") - # report("some texmf environment variables are fixed") if Kpse.fixtexmfvars(mpsengine) - command = [quoted(mpsengine),prognameflag(progname),iniflag,tcxflag,mpsformat].join(' ') - report(command) if getvariable('verbose') - system(command) - 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 = '' @@ -482,11 +525,12 @@ class TEX globpattern = "**/{#{formatpaths.join(',')}}/*/*.{fmt,efmt,ofmt,xfmt,mem}" report("format path: #{formatpaths.join(' ')}") # utilities - report + 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 - report("#{result}") + results.push("#{result}") end # formats cleanuptemprunfiles @@ -511,24 +555,23 @@ class TEX case format when /cont\-([a-z]+)/ then interface = $1.sub(/cont\-/,'') - report - report("testing interface #{interface}") + results.push('') + results.push("testing interface #{interface}") flags = ['--process','--batch','--once',"--interface=#{interface}",engineflag] -# to be adapted ! -result = Kpse.pipescript('newtexexec',tempfilename,flags) -# to just texexec + # 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 - report("#{$1} #{$2.gsub(/\(format.*$/,'')}".strip) + results.push("#{$1} #{$2.gsub(/\(format.*$/,'')}".strip) end end if logdata =~ /^\s*(ConTeXt)\s+(.*int:\s+[a-z]+.*?)\s*$/mois then - report("#{$1} #{$2}".gsub(/\s+/,' ').strip) + results.push("#{$1} #{$2}".gsub(/\s+/,' ').strip) end else - report("format #{format} does not work") + results.push("format #{format} does not work") end when /metafun/ then # todo @@ -536,12 +579,17 @@ result = Kpse.pipescript('newtexexec',tempfilename,flags) # todo end else - report("error in creating #{tempfilename('tex')}") + 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 @@ -628,8 +676,8 @@ result = Kpse.pipescript('newtexexec',tempfilename,flags) def scantexcontent(filename) if tex = File.open(filename) then - while str = tex.gets.chomp do - case str + while str = tex.gets do + case str.chomp when /^\%/o then # next when /\\(starttekst|stoptekst|startonderdeel|startdocument|startoverzicht)/o then @@ -709,13 +757,16 @@ result = Kpse.pipescript('newtexexec',tempfilename,flags) break elsif line =~ /<\?context\-directive\s+(.+?)\s+(.+?)\s+(.+?)\s*\?>/o then category, key, value = $1, $2, $3 - if category == 'job' then - if key == 'stylefile' then - tmp << "\\environment $value\n" - elsif key == 'module' then - tmp << "\\usemodule[$value]\n" - elsif key == 'interface' then - contextinterface = value + case category + when 'job' then + case key + when 'stylefile', 'environment' then + tmp << "\\environment $value\n" + when 'module' then + tmp << "\\usemodule[$value]\n" + when 'interface' then + contextinterface = value + end end end end @@ -742,7 +793,7 @@ class TEX getarrayvariable('files').each do |filename| setvariable('filename',filename) report("processing document '#{filename}'") - processcontextfile + processfile end reportruntime end @@ -804,7 +855,7 @@ class TEX if getvariable('nompmode') || getvariable('nomprun') || getvariable('automprun') then opt << "\\runMPgraphicsfalse\n" end - if getvariable('fastmode') && ! getvariable('fastdisabled') then + if getvariable('fast') && ! getvariable('fastdisabled') then opt << "\\fastmode\n" end if getvariable('silent') then @@ -942,7 +993,7 @@ 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].join(' ') + command = [quoted(texengine),prognameflag(progname),formatflag(texengine,texformat),runoptions(texengine),filename,texprocextras(texformat)].join(' ') report(command) if getvariable('verbose') system(command) else @@ -955,7 +1006,7 @@ class TEX 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].join(' ') + command = [quoted(mpsengine),prognameflag(progname),formatflag(mpsengine,mpsformat),runoptions(mpsengine),filename,mpsprocextras(mpsformat)].join(' ') report(command) if getvariable('verbose') system(command) else @@ -982,8 +1033,8 @@ class TEX 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 File.unsuffixed(filename) =~ /#{mpjobname}/ then # don't optimize + 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") @@ -991,18 +1042,52 @@ class TEX options.push("--translate=#{textranslation}") unless textranslation.empty? options.push("--batch") if getvariable('batchmode') options.push("--nonstop") if getvariable('nonstopmode') - return runtexexec(mpfile,options) + options.push("--output=ps") + return runtexexec(mpfile,options,2) end end return false end def runtexutil(filename=[], options=['--ref','--ij','--high']) - Kpse.runscript('texutil',filename,options) + begin + filename.each do |fname| + logger = Logger.new('TeXUtil') + if tu = TeXUtil::Converter.new(logger) and tu.loaded(fname) then + tu.saved if tu.processed + end + end + rescue + Kpse.runscript('texutil',filename,options) + end end - def runtexexec(filename=[], options=[]) - Kpse.runscript('texexec',filename,options) + # 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) @@ -1011,15 +1096,44 @@ class TEX ENV['TEXFONTMAPS'] = ".;\$TEXMF/fonts/map/{#{backend},pdftex,dvips,}//" end - def processcontextfile + def runbackend(jobname) + case validbackend(getvariable('backend')) + when 'dvipdfmx' then + fixbackendvars('dvipdfm') + system("dvipdfmx -d 4 #{File.unsuffixed(jobname)}") + when 'xetex' then + fixbackendvars('xetex') + system("xdv2pdf #{File.suffixed(jobname,'xdv')}") + when 'dvips' then + fixbackendvars('dvips') + mapfiles = '' + begin + if tuifile = File.suffixed(jobname,'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(jobname)}") + when 'pdftex' then + # no need for postprocessing + else + report("no postprocessing needed") + end + end + + def processfile takeprecautions jobname = getvariable('filename') - suffix = getvariable('suffix') - result = getvariable('result') + suffix = getvariable('suffix') + result = getvariable('result') - final = getvariable('final') + runonce = getvariable('once') + finalrun = getvariable('final') || (getvariable('arrange') && ! getvariable('noarrange')) if getvariable('autopath') then jobname = File.basename(jobname) @@ -1036,9 +1150,12 @@ class TEX orisuffix = jobsuffix # still needed ? + setvariable('nomprun',true) if orisuffix == 'mpx' # else cylic run + PDFview.closeall if getvariable('pdfopen') forcexml = jobsuffix === /(xml|fo|fox|rlg|exa|)/io # === returns true|false, =~ returns position + dummyfile = false # fuzzy code snippet: (we kunnen kpse: prefix gebruiken) @@ -1055,81 +1172,89 @@ class TEX unless dummyfile # we don't need this for xml scantexpreamble(File.suffixed(jobname,jobsuffix)) - scantexcontent(File.suffixed(jobname,jobsuffix)) if getvariable('texformat').standard? + scantexcontent(File.suffixed(jobname,jobsuffix)) if getvariable('texformats').standard? end result = File.suffixed(jobname,suffix) unless suffix.empty? pushresult(jobname,result) - if getvariable('simplerun') then - makeoptionfile(jobname,orisuffix,true,true,3) - problems = runtex(File.suffixed(jobname,jobsuffix)) - if problems then - ok = runtexutil(jobname) if getvariable('texutil') || getvariable('forcetexutil') - popresult(jobname,result) - end - File.silentrename(File.suffixed(jobname,'top'),File.suffixed(jobname,'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(jobname,s)) - end - ['mprun','mpgraph'].each do |s| - state.register(File.suffixed(jobname,s,'mp'),'randomseed') - # state.register(File.suffixed(jobname,s,'mpo')) - end - while ! stoprunning && (texruns < nofruns) && ok do - texruns += 1 - report("TeX run #{texruns}") - if texruns == 1 then - makeoptionfile(jobname,orisuffix,false,false,1) + method = validtexmethod(validtexformat(getvariable('texformats'))) + + report("tex processing method: #{method}") + + case method + + when 'context' then + + if getvariable('simplerun') || runonce then + makeoptionfile(jobname,orisuffix,true,true,3) + problems = runtex(File.suffixed(jobname,jobsuffix)) + unless problems then + ok = runtexutil(jobname) if getvariable('texutil') || getvariable('forcetexutil') + runbackend(jobname) + popresult(jobname,result) + end + File.silentrename(File.suffixed(jobname,'top'),File.suffixed(jobname,'tmp')) else - makeoptionfile(jobname,orisuffix,false,false,2) - end - ok = runtex(File.suffixed(jobname,jobsuffix)) - if ok && (nofruns > 1) then - unless getvariable('nomprun') then - mprundone = runtexmpjob(jobname, "mpgraph") - mprundone = runtexmpjob(jobname, "mprun") + 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(jobname,s)) + end + if getvariable('automprun') then # check this + ['mprun','mpgraph'].each do |s| + state.register(File.suffixed(jobname,s,'mp'),'randomseed') + # state.register(File.suffixed(jobname,s,'mpo')) + end + end + while ! stoprunning && (texruns < nofruns) && ok do + texruns += 1 + report("TeX run #{texruns}") + if texruns == 1 then + makeoptionfile(jobname,orisuffix,false,false,1) + else + makeoptionfile(jobname,orisuffix,false,false,2) + end + ok = runtex(File.suffixed(jobname,jobsuffix)) + if ok && (nofruns > 1) then + unless getvariable('nompmode') then + mprundone = runtexmpjob(jobname, "mpgraph") + mprundone = runtexmpjob(jobname, "mprun") + end + ok = runtexutil(jobname) + state.update + stoprunning = state.stable? + end + end + ok = runtexutil(jobname) if (nofruns == 1) && getvariable('texutil') + if ! problems && finalrun && (nofruns > 1) then + makeoptionfile(jobname,orisuffix,true,finalrun,4) + report("final TeX run #{texruns}") + problems = runtex(File.suffixed(jobname,jobsuffix)) + end + File.silentcopy(File.suffixed(jobname,'top'),File.suffixed(jobname,'tmp')) + ['tup','top'].each do |s| # previous tuo file / runtime option file + File.silentdelete(File.suffixed(jobname,s)) + end + unless problems then + runbackend(jobname) + popresult(jobname,result) end - ok = runtexutil(jobname) - state.update - stoprunning = state.stable? end - end - ok = runtexutil(jobname) if (nofruns == 1) && getvariable('texutil') - finalrun = getvariable('arrange') && ! getvariable('noarrange') - if ! problems && finalrun && (nofruns > 1) then - makeoptionfile(jobname,orisuffix,true,finalrun,4) - report("final TeX run #{texruns}") + + Kpse.runscript('ctxtools',jobname,'--purge') if getvariable('purge') + + when 'latex' then + problems = runtex(File.suffixed(jobname,jobsuffix)) - end - File.silentcopy(File.suffixed(jobname,'top'),File.suffixed(jobname,'tmp')) - ['tup','top'].each do |s| # previous tuo file / runtime option file - File.silentdelete(File.suffixed(jobname,s)) - end - case validbackend(getvariable('backend')) - when 'dvipdfmx' then - fixbackendvars('dvipdfm') - system("dvipdfmx -d 4 #{File.unsuffixed(jobname)}") - when 'xetex' then - fixbackendvars('xetex') - system("xdv2pdf #{File.suffixed(jobname,'xdv')}") - when 'dvips' then - fixbackendvars('dvips') - system("dvips #{File.unsuffixed(jobname)}") - when 'pdftex' then - # no need for postprocessing - else - report("no postprocessing needed") - end - popresult(jobname,result) - end - Kpse.runscript('ctxtools',jobname,'--purge') if getvariable('purge') + else + + problems = runtex(File.suffixed(jobname,jobsuffix)) + + end begin File.delete(File.suffixed(jobname,jobsuffix)) if dummyfile || forcexml @@ -1290,15 +1415,3 @@ class TEX end end - -class String - - def standard? - begin - self == 'standard' - rescue - false - end - end - -end diff --git a/scripts/context/ruby/base/texutil.rb b/scripts/context/ruby/base/texutil.rb new file mode 100644 index 000000000..2e5fbaaad --- /dev/null +++ b/scripts/context/ruby/base/texutil.rb @@ -0,0 +1,790 @@ +require "base/file" +require "base/logger" + +class String + + # real dirty, but inspect does a pretty good escaping but + # unfortunately puts quotes around the string so we need + # to strip these + + # def escaped + # self.inspect[1,self.inspect.size-2] + # end + + def escaped + str = self.inspect ; str[1,str.size-2] + end + + def splitdata + if self =~ /^\s*(.*?)\s*\{(.*)\}\s*$/o then + first, second = $1, $2 + if first.empty? then + [second.split(/\} \{/o)].flatten + else + [first.split(/\s+/o)] + [second.split(/\} \{/o)] + end + else + [] + end + end + +end + +class Logger + def banner(str) + report(str) + return "%\n% #{str}\n%\n" + end +end + +class TeXUtil + + class Plugin + + # we need to reset module data for each run; persistent data is + # possible, just don't reinitialize the data structures that need + # to be persistent; we reset afterwards becausethen we know what + # plugins are defined + + def initialize(logger) + @plugins = Array.new + @logger = logger + end + + def reset(name) + if @plugins.include?(name) then + begin + eval("#{name}").reset(@logger) + rescue Exception + @logger.report("fatal error in resetting plugin") + end + else + @logger.report("no plugin #{name}") + end + end + + def resets + @plugins.each do |p| + reset(p) + end + end + + def register(name, file=nil) # maybe also priority + if file then + begin + require("#{file.downcase.sub(/\.rb$/,'')}.rb") + rescue Exception + @logger.report("no plugin file #{file} for #{name}") + else + @plugins.push(name) + end + else + @plugins.push(name) + end + return self + end + + def reader(name, data=[]) + if @plugins.include?(name) then + begin + eval("#{name}").reader(@logger,data.flatten) + rescue Exception + @logger.report("fatal error in plugin reader #{name} (#{$!})") + end + else + @logger.report("no plugin #{name}") + end + end + + def readers(data=[]) + @plugins.each do |p| + reader(p,data.flatten) + end + end + + def writers(handle) + @plugins.each do |p| + begin + eval("#{p}").writer(@logger,handle) + rescue Exception + @logger.report("fatal error in plugin writer #{p} (#{$!})") + end + end + end + + def processors + @plugins.each do |p| + begin + eval("#{p}").processor(@logger) + rescue Exception + @logger.report("fatal error in plugin processor #{p} (#{$!})") + end + end + end + + end + + class Sorter + + def initialize(max=12) + @rep, @map, @exp = Hash.new, Hash.new, Hash.new + @max = max + @rexa, @rexb = nil, nil + end + + def replacer(from,to='') # and expand + @rep[from.escaped] = to || '' + end + + # sorter.reducer('ch', 'c') + # sorter.reducer('ij', 'y') + + def reducer(from,to='') + @map[from] = to || '' + end + + # sorter.expander('aeligature', 'ae') + # sorter.expander('ijligature', 'y') + + def expander(from,to=nil) + @exp[from] = to || from || '' + end + + # shortcut("\\ab\\cd\\e\\f", 'iacute') + # shortcut("\\\'\\i", 'iacute') + # shortcut("\\\'i", 'iacute') + # shortcut("\\\"e", 'ediaeresis') + # shortcut("\\\'o", 'oacute') + + def shortcut(from,to) + replacer(from,to) + expander(to) + end + + def prepare + @rexa = /(#{@rep.keys.join('|')})/o + if @map.size > 0 then + # watch out, order of match matters + @rexb = /(\\[a-zA-Z]+|#{@map.keys.join('|')}|.)\s*/o + else + @rexb = /(\\[a-zA-Z]+|.)\s*/o + end + end + + def remap(str) + str.gsub(@rexa) do + @rep[$1.escaped] + end.gsub(@rexb) do + token = $1.sub(/\\/o, '') + if @exp.key?(token) then + @exp[token].ljust(@max,' ') + elsif @map.key?(token) then + @map[token].ljust(@max,' ') + else + '' + end + end + end + + def preset(shortcuts=[],expansions=[],reductions=[]) + 'a'.upto('z') do |c| + expander(c) + end + shortcuts.each do |s| shortcut(s[0],s[1]) end + expansions.each do |e| expander(e[0],e[1]) end + reductions.each do |r| reducer(r[0],r[1]) end + end + + def simplify(str) + s = str.dup + # ^^ + # s.gsub!(/\^\^([a-f0-9][a-f0-9])/o, $1.hex.chr) + # \- || + s.gsub!(/(\\\-|\|\|)/o) do '-' end + # {} + s.gsub!(/\{\}/o) do '' end + # <*..> (internal xml entity) + s.gsub!(/<\*(.*?)>/o) do $1 end + # entities + s.gsub!(/\\getXMLentity\s*\{(.*?)\}/o) do $1 end + # elements + s.gsub!(/\<.*?>/o) do '' end + # what to do with xml and utf-8 + # \"e etc + # unknown \cs + s.gsub!(/\\[a-z][a-z]+\s*\{(.*?)\}/o) do $1 end + return s + end + + end + + class Plugin + + module MyFiles + + @@files = Hash.new + + def MyFiles::reset(logger) + @@files = Hash.new + end + + def MyFiles::reader(logger,data) + case data[0] + when 'b', 'e' then + if @@files.key?(data[1]) then + @@files[data[1]] += 1 + else + @@files[data[1]] = 1 + end + end + end + + def MyFiles::writer(logger,handle) + handle << logger.banner("loaded files: #{@@files.size}") + @@files.keys.sort.each do |k| + handle << "% > #{k} #{@@files[k]/2}\n" + end + end + + def MyFiles::processor(logger) + @@files.keys.sort.each do |k| + unless (@@files[k] % 2) == 0 then + logger.report("check loading of file #{k}, begin/end problem") + end + end + end + + end + + end + + class Plugin + + module MyCommands + + @@commands = [] + + def MyCommands::reset(logger) + @@commands = [] + end + + def MyCommands::reader(logger,data) + @@commands.push(data.shift+data.collect do |d| "\{#{d}\}" end.join) + end + + def MyCommands::writer(logger,handle) + handle << logger.banner("commands: #{@@commands.size}") + @@commands.each do |c| + handle << "#{c}\n" + end + end + + def MyCommands::processor(logger) + end + + end + + end + + class Plugin + + module MyExtras + + @@programs = [] + + def MyExtras::reset(logger) + @@programs = [] + end + + def MyExtras::reader(logger,data) + case data[0] + when 'p' then + @@programs.push(data[1]) if data[0] + end + end + + def MyExtras::writer(logger,handle) + handle << logger.banner("programs: #{@@programs.size}") + @@programs.each do |p| + handle << "% #{p} (#{@@programs[p]})\n" + end + end + + def MyExtras::processor(logger) + @@programs.each do |p| + cmd = "texmfstart #{@@programs[p]}" + logger.report("running #{cmd}") + system(cmd) + end + end + + end + + end + + class Plugin + + module MySynonyms + + class Synonym + + @@debug = true + + def initialize(t, c, k, d) + @type, @command, @key, @sortkey, @data = t, c, k, k, d + end + + attr_reader :type, :command, :key, :data + attr_reader :sortkey + attr_writer :sortkey + + def build(sorter) + @sortkey = sorter.remap(sorter.simplify(@key.downcase)) + if @sortkey.empty? then + @sortkey = sorter.remap(@command.downcase) + end + end + + def <=> (other) + @sortkey <=> other.sortkey + end + + def Synonym.flush(list,handle) + if @@debug then + list.each do |entry| + handle << "% [#{entry.sortkey}]\n" + end + end + list.each do |entry| + handle << "\\synonymentry{#{entry.type}}{#{entry.command}}{#{entry.key}}{#{entry.data}}\n" + end + end + + end + + @@synonyms = Hash.new + + def MySynonyms::reset(logger) + @@synonyms = Hash.new + end + + def MySynonyms::reader(logger,data) + if data[0] == 'e' then + @@synonyms[data[1]] = Array.new unless @@synonyms.key?(data[1]) + @@synonyms[data[1]].push(Synonym.new(data[1],data[2],data[3],data[4])) + end + end + + def MySynonyms::writer(logger,handle) + if @@synonyms.size > 0 then + @@synonyms.keys.sort.each do |s| + handle << logger.banner("synonyms: #{s} #{@@synonyms[s].size}") + Synonym.flush(@@synonyms[s],handle) + end + end + end + + def MySynonyms::processor(logger) + sorter = Sorter.new + sorter.preset(eval("MyKeys").shortcuts,eval("MyKeys").expansions,eval("MyKeys").reductions) + sorter.prepare + @@synonyms.keys.each do |s| + @@synonyms[s].each_index do |i| + @@synonyms[s][i].build(sorter) + end + @@synonyms[s] = @@synonyms[s].sort + end + end + + end + + end + + class Plugin + + module MyRegisters + + class Register + + @@debug = true + + @@howto = /^(.*?)\:\:(.*)$/o + @@split = ' && ' + + def initialize(state, t, l, k, e, s, p, r) + @state, @type, @location, @key, @entry, @seetoo, @page, @realpage = state, t, l, k, e, s, p, r + if @key =~ @@howto then @pagehowto, @key = $1, $2 else @pagehowto = '' end + if @entry =~ @@howto then @texthowto, @entry = $1, $2 else @texthowto = '' end + @key = @entry.dup if @key.empty? + @sortkey = @key.dup + @nofentries, @nofpages = 0, 0 + end + + attr_reader :state, :type, :location, :key, :entry, :seetoo, :page, :realpage, :texthowto, :pagehowto + attr_reader :sortkey + attr_writer :sortkey + + def build(sorter) + @entry, @key = [@entry, @key].collect do |target| + # +a+b+c &a&b&c a+b+c a&b&c + case target[0,1] + when '&' then target = target.sub(/^./o,'').gsub(/([^\\])\&/o) do "#{$1}#{@@split}" end + when '+' then target = target.sub(/^./o,'').gsub(/([^\\])\+/o) do "#{$1}#{@@split}" end + else target = target .gsub(/([^\\])[\&\+]/o) do "#{$1}#{@@split}" end + end + # {a}{b}{c} + # if target =~ /^\{(.*)\}$/o then + # $1.split(/\} \{/o).join(@@split) # space between } { is mandate + # else + target + # end + end + @sortkey = sorter.simplify(@key) + @sortkey = @sortkey.split(@@split).collect do |c| sorter.remap(c) end.join(@@split) + # if ($Key eq "") { $Key = SanitizedString($Entry) } + # if ($ProcessHigh){ $Key = HighConverted($Key) } + @sortkey = [ + @sortkey.downcase, + @sortkey, + @texthowto.ljust(10,' '), + @state, + @realpage.rjust(6,' '), + @pagehowto + ].join(@@split) + end + + def <=> (other) + @sortkey <=> other.sortkey + end + + # more module like + + @@savedhowto, @@savedfrom, @@savedto, @@savedentry = '', '', '', '', '' + @@collapse = false + + def Register.flushsavedline(handle) + if @@collapse && ! @@savedfrom.empty? then + if ! @@savedto.empty? then + handle << "\\registerfrom#{@@savedfrom}" + handle << "\\registerto#{@@savedto}" + else + handle << "\\registerpage#{@@savedfrom}" + end + end + @@savedhowto, @@savedfrom, @@savedto, @@savedentry = '', '', '', '' + end + + def Register.flush(list,handle) + # + # alphaclass can go, now flushed per class + # + if list.size > 0 then + @nofentries, @nofpages = 0, 0 + current, previous, howto = Array.new, Array.new, Array.new + lastpage, lastrealpage = '', '' + alphaclass, alpha = '', '' + @@savedhowto, @@savedfrom, @@savedto, @@savedentry = '', '', '', '' + + if @@debug then + list.each do |entry| + handle << "% [#{entry.sortkey[0,1]}] [#{entry.sortkey.gsub(/#{@@split}/o,'] [')}]\n" + end + end + list.each do |entry| + testalpha = entry.sortkey[0,1].downcase + if testalpha != alpha.downcase or alphaclass != entry.class then + alpha = testalpha + alphaclass = entry.class + if alpha != ' ' then + flushsavedline(handle) + character = alpha.sub(/([^a-zA-Z])/o) do "\\" + $1 end + handle << "\\registerentry{#{entry.type}}{#{character}}\n" + end + end + current = [entry.entry.split(@@split),'','',''].flatten + howto = current.collect do |e| + e + '::' + entry.texthowto + end + if howto[0] == previous[0] then + current[0] = '' + else + previous[0] = howto[0].dup + previous[1] = '' + previous[2] = '' + end + if howto[1] == previous[1] then + current[1] = '' + else + previous[1] = howto[1].dup + previous[2] = '' + end + if howto[2] == previous[2] then + current[2] = '' + else + previous[2] = howto[2].dup + end + copied = false + unless current[0].empty? then + Register.flushsavedline(handle) + handle << "\\registerentrya{#{entry.type}}{#{current[0]}}\n" + copied = true + end + unless current[1].empty? then + Register.flushsavedline(handle) + handle << "\\registerentryb{#{entry.type}}{#{current[1]}}\n" + copied = true + end + unless current[2].empty? then + Register.flushsavedline(handle) + handle << "\\registerentryc{#{entry.type}}{#{current[2]}}\n" + copied = true + end + @nofentries += 1 if copied + if entry.realpage.to_i == 0 then + Register.flushsavedline(handle) + handle << "\\registersee{#{entry.type}}{#{entry.pagehowto},#{entry.texthowto}}{#{entry.seetoo}}{#{entry.page}}\n" ; + lastpage, lastrealpage = entry.page, entry.realpage + elsif @@savedhowto != entry.pagehowto and ! entry.pagehowto.empty? then + @@savedhowto = entry.pagehowto + end + if copied || ! ((lastpage == entry.page) && (lastrealpage == entry.realpage)) then + nextentry = "{#{entry.type}}{#{previous[0]}}{#{previous[1]}}{#{previous[2]}}{#{entry.pagehowto},#{entry.texthowto}}" + savedline = "{#{entry.type}}{#{@@savedhowto},#{entry.texthowto}}{#{entry.location}}{#{entry.page}}{#{entry.realpage}}" + if entry.state == 1 then # from + Register.flushsavedline(handle) + handle << "\\registerfrom#{savedline}\n" + elsif entry.state == 3 then # to + Register.flushsavedline(handle) + handle << "\\registerto#{savedline}\n" + elsif @@collapse then + if savedentry != nextentry then + savedFrom = savedline + else + savedTo, savedentry = savedline, nextentry + end + else + handle << "\\registerpage#{savedline}\n" + end + @nofpages += 1 + lastpage, lastrealpage = entry.page, entry.realpage + end + end + Register.flushsavedline(handle) + end + end + + end + + @@registers = Hash.new + + def MyRegisters::reset(logger) + @@registers = Hash.new + end + + def MyRegisters::reader(logger,data) + case data[0] + when 'f' then + @@registers[data[1]] = Array.new unless @@registers.key?(data[1]) + @@registers[data[1]].push(Register.new(1,data[1],data[2],data[3],data[4],nil,data[5],data[6])) + when 'e' then + @@registers[data[1]] = Array.new unless @@registers.key?(data[1]) + @@registers[data[1]].push(Register.new(2,data[1],data[2],data[3],data[4],nil,data[5],data[6])) + when 't' then + @@registers[data[1]] = Array.new unless @@registers.key?(data[1]) + @@registers[data[1]].push(Register.new(3,data[1],data[2],data[3],data[4],nil,data[5],data[6])) + when 's' then + @@registers[data[1]] = Array.new unless @@registers.key?(data[1]) + @@registers[data[1]].push(Register.new(4,data[1],data[2],data[3],data[4],data[5],data[6],nil)) + end + end + + def MyRegisters::writer(logger,handle) + if @@registers.size > 0 then + @@registers.keys.sort.each do |s| + handle << logger.banner("registers: #{s} #{@@registers[s].size}") + Register.flush(@@registers[s],handle) + # report("register #{@@registers[s].class}: #{@@registers[s].@nofentries} entries and #{@@registers[s].@nofpages} pages") + end + end + end + + def MyRegisters::processor(logger) + sorter = Sorter.new + sorter.preset(eval("MyKeys").shortcuts,eval("MyKeys").expansions,eval("MyKeys").reductions) + sorter.prepare + @@registers.keys.each do |s| + @@registers[s].each_index do |i| + @@registers[s][i].build(sorter) + end + @@registers[s] = @@registers[s].sort + end + end + + end + + end + + class Plugin + + module MyPlugins + + @@plugins = nil + + def MyPlugins::reset(logger) + @@plugins = nil + end + + def MyPlugins::reader(logger,data) + @@plugins = Plugin.new(logger) unless @@plugins + case data[0] + when 'r' then + logger.report("registering plugin #{data[1]}") + @@plugins.register(data[1],data[2]) + when 'd' then + begin + @@plugins.reader(data[1],data[2,data.length-1]) + rescue + @@plugins.reader(data[1],['error']) + end + end + end + + def MyPlugins::writer(logger,handle) + @@plugins.writers(handle) if @@plugins + end + + def MyPlugins::processor(logger) + @@plugins.processors if @@plugins + end + + end + + end + + class Plugin + + module MyKeys + + @@shortcuts = Array.new + @@expansions = Array.new + @@reductions = Array.new + + def MyKeys::shortcuts + @@shortcuts + end + def MyKeys::expansions + @@expansions + end + def MyKeys::reductions + @@reductions + end + + def MyKeys::reset(logger) + @@shortcuts = Array.new + @@expansions = Array.new + @@reductions = Array.new + end + + def MyKeys::reader(logger,data) + key = data.shift + grp = data.shift # language code, todo + case key + when 's' then @@shortcuts.push(data) + when 'e' then @@expansions.push(data) + when 'r' then @@reductions.push(data) + end + end + + def MyKeys::writer(logger,handle) + end + + def MyKeys::processor(logger) + logger.report("shortcuts: #{@@shortcuts.size}") # logger.report(@@shortcuts.inspect) + logger.report("expansions: #{@@expansions.size}") # logger.report(@@expansions.inspect) + logger.report("reductions: #{@@reductions.size}") # logger.report(@@reductions.inspect) + end + + end + + end + + class Converter + + def initialize(logger=nil) + if @logger = logger then + def report(str) + @logger.report(str) + end + def banner(str) + @logger.banner(str) + end + else + @logger = self + def report(str) + puts(str) + end + def banner(str) + puts(str) + end + end + @filename = 'texutil' + @fatalerror = false + @plugins = Plugin.new(@logger) + ['MyFiles', 'MyCommands', 'MySynonyms', 'MyRegisters', 'MyExtras', 'MyPlugins', 'MyKeys'].each do |p| + @plugins.register(p) + end + end + + def loaded(filename) + begin + report("parsing file #{filename}") + File.open(File.suffixed(filename,'tui')).each do |line| + case line.chomp + when /^f (.*)$/o then @plugins.reader('MyFiles', $1.splitdata) + when /^c (.*)$/o then @plugins.reader('MyCommands', $1.splitdata) + when /^e (.*)$/o then @plugins.reader('MyExtras', $1.splitdata) + when /^s (.*)$/o then @plugins.reader('MySynonyms', $1.splitdata) + when /^r (.*)$/o then @plugins.reader('MyRegisters',$1.splitdata) + when /^p (.*)$/o then @plugins.reader('MyPlugins', $1.splitdata) + when /^x (.*)$/o then @plugins.reader('MyKeys', $1.splitdata) + else report("unknown entry #{line[0,1]} in line #{line.chomp}") + end + end + rescue + report("fatal error in parsing file (#{$!})") + @filename = 'texutil' + else + @filename = filename + end + end + + def processed + @plugins.processors + return true # for the moment + end + + def saved(filename=@filename) + if @fatalerror then + report("fatal error, no tuo file saved") + else + begin + if f = File.open(File.suffixed(filename,'tuo'),'w') then + @plugins.writers(f) + f.close + end + rescue + report("fatal error when saving file (#{$!})") + else + report("tuo file saved") + end + end + @plugins.resets + end + + def reset + @plugins.resets + end + + end + +end diff --git a/scripts/context/ruby/base/variables.rb b/scripts/context/ruby/base/variables.rb index 0c495d22d..5cbc5ba53 100644 --- a/scripts/context/ruby/base/variables.rb +++ b/scripts/context/ruby/base/variables.rb @@ -26,6 +26,14 @@ module Variables if @variables.key?(key) then @variables[key] else default end end + def checkedvariable(str,default='') + if @variables.key?(key) then + if @variables[key].empty? then default else @variables[key] end + else + default + end + end + def report(*str) @logger.report(*str) end diff --git a/scripts/context/ruby/ctxtools.rb b/scripts/context/ruby/ctxtools.rb index c90299b0a..c89b1a30b 100644 --- a/scripts/context/ruby/ctxtools.rb +++ b/scripts/context/ruby/ctxtools.rb @@ -31,6 +31,7 @@ require 'base/system' require 'rexml/document' require 'ftools' +require 'kconv' exit if defined?(REQUIRE2LIB) @@ -746,12 +747,15 @@ class Language @language = language @filenames = filenames @remapping = Array.new + @unicode = Hash.new @encoding = encoding @data = '' @read = '' preload_accents() + preload_unicode() if @commandline.option('utf8') case @encoding.downcase when 't1', 'ec', 'cork' then preload_vector('ec') + when 'y', 'texnansi' then preload_vector('texnansi') end end @@ -773,15 +777,13 @@ class Language @filenames.each do |fileset| [fileset].flatten.each do |filename| begin - if filename = located(filename) then - data = IO.read(filename) + if fname = located(filename) then + data = IO.read(fname) @data += data.gsub(/\%.*$/, '') data.gsub!(/(\\patterns|\\hyphenation)\s*\{.*/mo) do '' end - @read += "\n% preamble of file #{filename}\n\n#{data}\n" - report("file #{filename} is loaded") + @read += "\n% preamble of file #{fname}\n\n#{data}\n" + report("file #{fname} is loaded") break # next fileset - else - report("file #{filename} is not found") end rescue report("file #{filename} is not readable") @@ -808,9 +810,17 @@ class Language end end report("#{n} changes in patterns and exceptions") - return n + if @commandline.option('utf8') then + n = 0 + @data.gsub!(/\[(.*?)\]/o) do + n += 1 + @unicode[$1] || $1 + end + report("#{n} unicode utf8 entries") + end + return true else - return 0 + return false end end @@ -850,6 +860,22 @@ class Language end end + def triggerunicode + if @commandline.option('utf8') then + "% xetex needs utf8 encoded patterns and for patterns\n" + + "% coded as such we need to enable this regime when\n" + + "% not in xetex; this code will be moved into context\n" + + "% as soon as we've spread the generic patterns\n" + + "\n" + + "\\ifx\\XeTeXversion\\undefined \\else\n" + + " \\ifx\\enableregime\\undefined \\else\n" + + " \\enableregime[utf]\n" + + " \\fi\n" + + "\\fi\n" + + "\n" + end + end + def save xml = @commandline.option("xml") @@ -938,11 +964,13 @@ class Language data += $1 + "\n" end data.gsub!(/(\s*\n\s*)+/mo, "\n") + f << banner f << comment("context pattern file, see #{commentfile} for original comment") f << comment("source of data: #{@filenames.join(' ')}") f << description f << comment("begin pattern data") + f << triggerunicode f << content('patterns', data) f << comment("end pattern data") f.close @@ -964,11 +992,12 @@ class Language data.gsub!(/(\s*\n\s*)+/mo, "\n") f << banner f << comment("context hyphenation file, see #{commentfile} for original comment") - f.<< comment("source of data: #{@filenames.join(' ')}") + f << comment("source of data: #{@filenames.join(' ')}") f << description - f.<< comment("begin hyphenation data") + f << comment("begin hyphenation data") + f << triggerunicode f << content('hyphenation', data) - f.<< comment("end hyphenation data") + f << comment("end hyphenation data") f.close report("exceptions saved in file #{hypname}") else @@ -1005,10 +1034,10 @@ class Language def located(filename) begin - filename = `kpsewhich -progname=context #{filename}`.chomp - if FileTest.file?(filename) then - report("using file #{filename}") - return filename + fname = `kpsewhich -progname=context #{filename}`.chomp + if FileTest.file?(fname) then + report("using file #{fname}") + return fname else report("file #{filename} is not present") return nil @@ -1041,6 +1070,26 @@ class Language end + def preload_unicode + + # \definecharacter Agrave {\uchar0{192}} + + begin + if filename = located("enco-uc.tex") then + if data = IO.read(filename) then + report("preloading unicode conversions") + data.scan(/\\definecharacter\s*(.+?)\s*\{\\uchar\{*(\d+)\}*\s*\{(\d+)\}/o) do + one, two, three = $1, $2.to_i, $3.to_i + @unicode[one] = [(two*256 + three)].pack("U") + end + end + end + rescue + report("error in loading unicode mapping (#{$!})") + end + + end + def preload_vector(encoding='') # funny polish @@ -1279,7 +1328,7 @@ commandline.registeraction('documentation', 'generate documentation [--type=] [f commandline.registeraction('filterpages') # no help, hidden temporary feature commandline.registeraction('purgeallfiles') # no help, compatibility feature -commandline.registeraction('patternfiles', 'generate pattern files [--all] [languagecode]') +commandline.registeraction('patternfiles', 'generate pattern files [--all --xml --utf8] [languagecode]') commandline.registeraction('dpxmapfiles', 'convert pdftex mapfiles to dvipdfmx [--force] [texmfroot]') @@ -1291,6 +1340,7 @@ commandline.registerflag('pipe') commandline.registerflag('all') commandline.registerflag('xml') commandline.registerflag('log') +commandline.registerflag('utf8') # general diff --git a/scripts/context/ruby/newtexexec.rb b/scripts/context/ruby/newtexexec.rb index 758a42d89..0d9602312 100644 --- a/scripts/context/ruby/newtexexec.rb +++ b/scripts/context/ruby/newtexexec.rb @@ -1,4 +1,4 @@ -banner = ['TeXExec', 'version 6.0.1', '1997-2005', 'PRAGMA ADE/POD'] +banner = ['TeXExec', 'version 6.1.0', '1997-2005', 'PRAGMA ADE/POD'] unless defined? ownpath ownpath = $0.sub(/[\\\/][a-z0-9\-]*?\.rb/i,'') @@ -11,6 +11,7 @@ require 'base/variables' require 'base/system' require 'base/tex' +require 'base/texutil' require 'ftools' # needed ? @@ -25,13 +26,6 @@ class Commands def make if job = TEX.new(logger) then - # prepare, move to TEX ? - if @commandline.option('fast') then - report('using existing database') - else - report('updating file database') - Kpse.update - end prepare(job) # bonus, overloads language switch ! job.setvariable('language','all') if @commandline.option('all') @@ -56,6 +50,14 @@ class Commands end end + def main + if @commandline.arguments.length>0 then + process + else + help + end + end + def process if job = TEX.new(logger) then job.setvariable('files',@commandline.arguments) @@ -65,14 +67,6 @@ class Commands end end - def main - if @commandline.arguments.length>0 then - process - else - help - end - end - def mptex if job = TEX.new(logger) then job.setvariable('files',@commandline.arguments) @@ -181,11 +175,11 @@ class Commands end def modules - msuffixes = ['tex','mp','pl','pm','rb'] if job = TEX.new(logger) then prepare(job) job.cleanuptemprunfiles files = @commandline.arguments.sort + msuffixes = ['tex','mp','pl','pm','rb'] if files.length > 0 then files.each do |fname| fnames = Array.new @@ -491,6 +485,8 @@ class Commands job.setvariable('backend','xetex') elsif @commandline.oneof('aleph') then job.setvariable('backend','dvipdfmx') + elsif @commandline.oneof('dvips','ps') then + job.setvariable('backend','dvips') else job.setvariable('backend','standard') end @@ -512,8 +508,6 @@ end logger = Logger.new(banner.shift) commandline = CommandLine.new -# actions - commandline.registeraction('make', 'make formats') commandline.registeraction('check', 'check versions') commandline.registeraction('process', 'process file') @@ -572,6 +566,9 @@ commandline.registerflag('dvipdfm') commandline.registerflag('dpx') commandline.registerflag('dpm') +commandline.registerflag('dvips') +commandline.registerflag('ps') + commandline.registerflag('xetex') commandline.registerflag('xtx') diff --git a/scripts/context/ruby/newtexutil.rb b/scripts/context/ruby/newtexutil.rb index 001bdde68..b8cc99ccf 100644 --- a/scripts/context/ruby/newtexutil.rb +++ b/scripts/context/ruby/newtexutil.rb @@ -1,557 +1,14 @@ -#D Plugins -#D -#D test.pm: -#D -#D \starttypen -#D see plugtest.pm -#D \stoptypen -#D -#D utility format: -#D -#D \starttypen -#D p u {name} {data} {data} ... -#D \stoptypen +require 'base/logger' +require 'base/texutil' -# my $pm_path ; +logger = Logger.new('TeXUtil') -# BEGIN - # { $pm_path = "$FindBin::Bin/" ; - # if ($pm_path eq "") { $pm_path = "./" } } +filename = ARGV[0] || 'tuitest' -# use lib $pm_path ; - -# my %UserPlugIns ; - -# sub HandlePlugIn - # { if ($RestOfLine =~ /\s*u\s*\{(.*?)\}\s*(.*)\s*/io) - # { my $tag = $1 ; - # my $arg = $2 ; - # if (! defined($UserPlugIns{$tag})) - # { $UserPlugIns{$tag} = 1 ; - # eval("use $tag") ; - # my $result = $tag->identify ; - # if ($result ne "") - # { Report ("PlugInInit", "$tag -> $result") } - # else - # { Report ("PlugInInit", $tag ) } - # $tag->initialize() } - # if (defined($UserPlugIns{$tag})) - # { $arg =~ s/\{(.*)\}/$1/o ; - # my @args = split(/\}\s*\{/o, $arg) ; - # $tag->handle(@args) } } } - -# sub FlushPlugIns - # { foreach my $tag (keys %UserPlugIns) - # { my @report = $tag->report ; - # foreach $rep (@report) - # { my ($key,$val) = split (/\s*\:\s*/,$rep) ; - # if ($val ne "") - # { Report ("PlugInReport", "$tag -> $key -> $val") } - # else - # { Report ("PlugInReport", "$tag -> $key") } } - # $tag->process ; - # print TUO "%\n" . "% $Program / " . $tag->identify . "\n" . "%\n" ; - # foreach my $str ($tag->results) - # { print TUO "\\plugincommand\{$str\}\n" } } } - -require "base/file" - -def report(str) - puts(str) +if tu = TeXUtil::Converter.new(logger) and tu.loaded(filename) then + tu.saved if tu.processed end -class String - - # real dirty, but inspect does a pretty good escaping but - # unfortunately puts quotes around the string so we need - # to strip these - - # def escaped - # self.inspect[1,self.inspect.size-2] - # end - - def escaped - str = self.inspect ; str[1,str.size-2] - end - -end - -class Sorter - - def initialize(max=12) - @rep, @map, @exp = Hash.new, Hash.new, Hash.new - @max = max - @rexa, @rexb = nil, nil - end - - def replace(from,to='') # and expand - @rep[from.escaped] = to || '' - end - - # sorter.reduce('ch', 'c') - # sorter.reduce('ij', 'y') - - def reduce(from,to='') - @map[from] = to || '' - end - - # sorter.expand('aeligature', 'ae') - # sorter.expand('ijligature', 'y') - - def expand(from,to=nil) - @exp[from] = to || from || '' - end - - # shortcut("\\ab\\cd\\e\\f", 'iacute') - # shortcut("\\\'\\i", 'iacute') - # shortcut("\\\'i", 'iacute') - # shortcut("\\\"e", 'ediaeresis') - # shortcut("\\\'o", 'oacute') - - def shortcut(from,to) - replace(from,to) - expand(to) - end - - def prepare - @rexa = /(#{@rep.keys.join('|')})/o - if @map.size > 0 then - # watch out, order of match matters - @rexb = /(\\[a-zA-Z]+|#{@map.keys.join('|')}|.)\s*/o - else - @rexb = /(\\[a-zA-Z]+|.)\s*/o - end - end - - def remap(str) - str.gsub(@rexa) do - @rep[$1.escaped] - end.gsub(@rexb) do - token = $1.sub(/\\/o, '') - if @map.key?(token) then - @map[token].ljust(@max,' ') - elsif @exp.key?(token) then - @exp[token].split('').collect do |t| - t.ljust(@max,' ') - end.join('') - else - '' - end - end - end - - def remap(str) - str.gsub(@rexa) do - @rep[$1.escaped] - end.gsub(@rexb) do - token = $1.sub(/\\/o, '') - if @exp.key?(token) then - @exp[token].ljust(@max,' ') - elsif @map.key?(token) then - @map[token].ljust(@max,' ') - else - '' - end - end - end - - def preset(language='') - 'a'.upto('z') do |c| - expand(c) - end - shortcut("\\\'\\i", 'iacute') - shortcut("\\\'i", 'iacute') - shortcut("\\\"e", 'ediaeresis') - shortcut("\\\'o", 'oacute') - expand('aeligature', 'ae') - expand('ijligature', 'y') - expand('eacute') - expand('egrave') - expand('ediaeresis') - # reduce('ch', 'c') - # reduce('ij', 'y') - # expand('aeligature', 'ae') - # expand('ijligature', 'y') - # expand('tex') - end - - def simplify(str) - s = str.dup - # ^^ - # s.gsub!(/\^\^([a-f0-9][a-f0-9])/o, $1.hex.chr) - # \- || - s.gsub!(/(\\\-|\|\|)/o) do '-' end - # {} - s.gsub!(/\{\}/o) do '' end - # <*..> (internal xml entity) - s.gsub!(/<\*(.*?)>/o) do $1 end - # entities - s.gsub!(/\\getXMLentity\s*\{(.*?)\}/o) do $1 end - # elements - s.gsub!(/\<.*?>/o) do '' end - # what to do with xml and utf-8 - # \"e etc - # unknown \cs - s.gsub!(/\\[a-z][a-z]+\s*\{(.*?)\}/o) do $1 end - return s - end - -end - -class Synonym - - @@debug = true - - def initialize(t, c, k, d) - @type, @command, @key, @sortkey, @data = t, c, k, k, d - end - - attr_reader :type, :command, :key, :data - attr_reader :sortkey - attr_writer :sortkey - - def build(sorter) - @sortkey = sorter.remap(sorter.simplify(@key.downcase)) - if @sortkey.empty? then - @sortkey = sorter.remap(@command.downcase) - end - end - - def <=> (other) - @sortkey <=> other.sortkey - end - - def Synonym.flush(list,handle) - if @@debug then - list.each do |entry| - handle << "% [#{entry.sortkey}]\n" - end - end - list.each do |entry| - handle << "\\synonymentry{#{entry.type}}{#{entry.command}}{#{entry.key}}{#{entry.data}}\n" - end - end - -end - -class Register - - @@debug = true - - @@howto = /^(.*?)\:\:(.*)$/o - @@split = ' && ' - - def initialize(state, t, l, k, e, s, p, r) - @state, @type, @location, @key, @entry, @seetoo, @page, @realpage = state, t, l, k, e, s, p, r - if @key =~ @@howto then @pagehowto, @key = $1, $2 else @pagehowto = '' end - if @entry =~ @@howto then @texthowto, @entry = $1, $2 else @texthowto = '' end - @key = @entry.dup if @key.empty? - @sortkey = @key.dup - end - - attr_reader :state, :type, :location, :key, :entry, :seetoo, :page, :realpage, :texthowto, :pagehowto - attr_reader :sortkey - attr_writer :sortkey - - def build(sorter) - @entry, @key = [@entry, @key].collect do |target| - # +a+b+c &a&b&c a+b+c a&b&c - case target[0,1] - when '&' then target = target.sub(/^./o,'').gsub(/([^\\])\&/o) do "#{$1}#{@@split}" end - when '+' then target = target.sub(/^./o,'').gsub(/([^\\])\+/o) do "#{$1}#{@@split}" end - else target = target .gsub(/([^\\])[\&\+]/o) do "#{$1}#{@@split}" end - end - # {a}{b}{c} - if target =~ /^\{(.*)\}$/o then - $1.split(/\} \{/o).join(@@split) # space between } { is mandate - else - target - end - end - @sortkey = sorter.simplify(@key) - @sortkey = @sortkey.split(@@split).collect do |c| sorter.remap(c) end.join(@@split) - # if ($Key eq "") { $Key = SanitizedString($Entry) } - # if ($ProcessHigh){ $Key = HighConverted($Key) } - @sortkey = [ - @sortkey.downcase, - @sortkey, - @texthowto.ljust(10,' '), - @state, - @realpage.rjust(6,' '), - @pagehowto - ].join(@@split) - end - - def <=> (other) - @sortkey <=> other.sortkey - end - - # more module like - - @@savedhowto, @@savedfrom, @@savedto, @@savedentry = '', '', '', '', '' - @@collapse = false - - def Register.flushsavedline(handle) - if @@collapse && ! @@savedfrom.empty? then - if ! @@savedto.empty? then - handle << "\\registerfrom#{@@savedfrom}" - handle << "\\registerto#{@@savedto}" - else - handle << "\\registerpage#{@@savedfrom}" - end - end - @@savedhowto, @@savedfrom, @@savedto, @@savedentry = '', '', '', '' - end - - def Register.flush(list,handle) - # - # alphaclass can go, now flushed per class - # - if list.size > 0 then - nofentries, nofpages = 0, 0 - current, previous, howto = Array.new, Array.new, Array.new - lastpage, lastrealpage = '', '' - alphaclass, alpha = '', '' - @@savedhowto, @@savedfrom, @@savedto, @@savedentry = '', '', '', '' - - if @@debug then - list.each do |entry| - handle << "% [#{entry.sortkey[0,1]}] [#{entry.sortkey.gsub(/#{@@split}/o,'] [')}]\n" - end - end - list.each do |entry| - testalpha = entry.sortkey[0,1].downcase - if testalpha != alpha.downcase or alphaclass != entry.class then - alpha = testalpha - alphaclass = entry.class - if alpha != ' ' then - flushsavedline(handle) - character = alpha.sub(/([^a-zA-Z])/o) do "\\" + $1 end - handle << "\\registerentry{#{entry.type}}{#{character}}\n" - end - end - current = [entry.entry.split(@@split),'','',''].flatten - howto = current.collect do |e| - e + '::' + entry.texthowto - end - if howto[0] == previous[0] then - current[0] = '' - else - previous[0] = howto[0].dup - previous[1] = '' - previous[2] = '' - end - if howto[1] == previous[1] then - current[1] = '' - else - previous[1] = howto[1].dup - previous[2] = '' - end - if howto[2] == previous[2] then - current[2] = '' - else - previous[2] = howto[2].dup - end - copied = false - unless current[0].empty? then - Register.flushsavedline(handle) - handle << "\\registerentrya{#{entry.type}}{#{current[0]}}\n" - copied = true - end - unless current[1].empty? then - Register.flushsavedline(handle) - handle << "\\registerentryb{#{entry.type}}{#{current[1]}}\n" - copied = true - end - unless current[2].empty? then - Register.flushsavedline(handle) - handle << "\\registerentryc{#{entry.type}}{#{current[2]}}\n" - copied = true - end - nofentries += 1 if copied - if entry.realpage.to_i == 0 then - Register.flushsavedline(handle) - handle << "\\registersee{#{entry.type}}{#{entry.pagehowto},#{entry.texthowto}}{#{entry.seetoo}}{#{entry.page}}\n" ; - lastpage, lastrealpage = entry.page, entry.realpage - elsif @@savedhowto != entry.pagehowto and ! entry.pagehowto.empty? then - @@savedhowto = entry.pagehowto - end - if copied || ! ((lastpage == entry.page) && (lastrealpage == entry.realpage)) then - nextentry = "{#{entry.type}}{#{previous[0]}}{#{previous[1]}}{#{previous[2]}}{#{entry.pagehowto},#{entry.texthowto}}" - savedline = "{#{entry.type}}{#{@@savedhowto},#{entry.texthowto}}{#{entry.location}}{#{entry.page}}{#{entry.realpage}}" - if entry.state == 1 then # from - Register.flushsavedline(handle) - handle << "\\registerfrom#{savedline}\n" - elsif entry.state == 3 then # to - Register.flushsavedline(handle) - handle << "\\registerto#{savedline}\n" - elsif @@collapse then - if savedentry != nextentry then - savedFrom = savedline - else - savedTo, savedentry = savedline, nextentry - end - else - handle << "\\registerpage#{savedline}\n" - end - nofpages += 1 - lastpage, lastrealpage = entry.page, entry.realpage - end - end - Register.flushsavedline(handle) - report("register #{list[0].class}: #{nofentries} entries and #{nofpages} pages") - end - end - -end - -class TeXUtil - - # how to deal with encoding: - # - # load context enco-* file - - def initialize - @commands = [] - @programs = [] - @synonyms = Hash.new - @registers = Hash.new - @files = Hash.new - @filename = 'texutil' - @fatalerror = false - end - - def loaded(filename) - # begin - File.open(File.suffixed(filename,'tui')).each do |line| - case line.chomp - # f b|e {filename} - when /^f (b|e) \{(.*)\}$/o then - if @files.key?($2) then @files[$2] += 1 else @files[$2] = 1 end - # c commmand - when /^c (.*)$/o then - @commands.push($1) - # e p {program data} - when /^e p \{(.*)\}$/o then - @programs.push($1) - # s e {type}{command}{key}{associated data} - when /^s e \{(.*)\}\s*\{(.*)\}\s*\{(.*)\}\s*\{(.*)\}\s*$/o then - @synonyms[$1] = Array.new unless @synonyms.key?($1) - @synonyms[$1].push(Synonym.new($1,$2,$3,$4)) - # from: r f - when /^r f \{(.*)\}\s*\{(.*)\}\s*\{(.*)\}\s*\{(.*)\}\s*\{(.*)\}\s*\{(.*)\}\s*/o then - @registers[$1] = Array.new unless @registers.key?($1) - @registers[$1].push(Register.new(1,$1,$2,$3,$4,nil,$5,$6)) - # entry: r e {type}{location}{key}{entry}{page}{realpage} - when /^r e \{(.*)\}\s*\{(.*)\}\s*\{(.*)\}\s*\{(.*)\}\s*\{(.*)\}\s*\{(.*)\}\s*/o then - @registers[$1] = Array.new unless @registers.key?($1) - @registers[$1].push(Register.new(2,$1,$2,$3,$4,nil,$5,$6)) - # from: r t - when /^r t \{(.*)\}\s*\{(.*)\}\s*\{(.*)\}\s*\{(.*)\}\s*\{(.*)\}\s*\{(.*)\}\s*/o then - @registers[$1] = Array.new unless @registers.key?($1) - @registers[$1].push(Register.new(3,$1,$2,$3,$4,nil,$5,$6)) - # see: r s {type}{location}{key}{entry}{seetoo}{page} - when /^r s \{(.*)\}\s*\{(.*)\}\s*\{(.*)\}\s*\{(.*)\}\s*\{(.*)\}\s*\{(.*)\}\s*/o then - @registers[$1] = Array.new unless @registers.key?($1) - @registers[$1].push(Register.new(4,$1,$2,$3,$4,$5,$6,nil)) - when /^k /o then - # key - when /^p /o then - # plugin - when /^q/o then - break - else - report("unknown entry #{line}") - end - end - # rescue - # report("error in parsing file (#{$!})") - # @filename = 'texutil' - # else - @filename = filename - # end - end - - def sorted - sorter = Sorter.new - sorter.preset - sorter.prepare - [@synonyms,@registers].each do |target| - target.keys.each do |s| - target[s].each_index do |i| - target[s][i].build(sorter) - end - target[s] = target[s].sort - end - end - end - - def banner(str) - report(str) - return "%\n% #{str}\n%\n" - end - - def saved(filename=@filename) - if @fatalerror then - report("fatal error, no tuo file saved") - else - # begin - if f = File.open(File.suffixed(filename,'tuo'),'w') then - if @files.size > 0 then - f << banner("loaded files: #{@files.size}") - @files.keys.sort.each do |k| - unless (@files[k] % 2) == 0 then - report("check loading of file #{k}, begin/end problem") - end - f << "% > #{k} #{@files[k]/2}\n" - end - end - if @commands.size > 0 then - f << banner("commands: #{@commands.size}") - @commands.each do |c| - f << "#{c}\n" - end - end - if @synonyms.size > 0 then - @synonyms.keys.sort.each do |s| - f << banner("synonyms: #{s} #{@synonyms[s].size}") - Synonym.flush(@synonyms[s],f) - end - end - if @registers.size > 0 then - @registers.keys.sort.each do |s| - f << banner("registers: #{s} #{@registers[s].size}") - Register.flush(@registers[s],f) - end - end - if @programs.size > 0 then - f << banner("programs: #{@programs.size}") - @programs.each do |p| - f << "% #{p} (#{@programs[p]})\n" - end - end - f.close - @programs.each do |p| - cmd = "texmfstart #{@programs[p]}" - report("running #{cmd}") - system(cmd) - end - end - # rescue - # report("fatal error when saving file (#{$!})") - # end - end - end - -end - -if tu = TeXUtil.new and tu.loaded('tuitest') then - tu.sorted - tu.saved -end - - # ShowBanner ; - # if ($UnknownOptions ) { ShowHelpInfo } # not yet done # elsif ($ProcessReferences) { HandleReferences } # elsif ($ProcessFigures ) { HandleFigures } @@ -563,49 +20,3 @@ end # elsif ($FilterPages ) { my $args = @ARGV.join(' ') ; system("texmfstart ctxtools --filter $args") } # elsif ($ProcessHelp ) { ShowHelpInfo } # redundant # else { ShowHelpInfo } - -#D So far. - - -# # # # keep - -# sorter = Sorter.new -# sorter.reduce('ch', 'c') -# sorter.reduce('ij', 'y') - -# sorter.expand('aeligature', 'ae') -# sorter.expand('ijligature', 'y') - -# str = Array.new - -# str.push 'aex c abc' -# str.push 'aex h abc' -# str.push 'aex ch abc' -# str.push 'aex a abc' -# str.push 'aex b abc' -# str.push 'aex c def' -# str.push 'aex h def' -# str.push 'aex ch def' -# str.push 'aex a def' -# str.push 'aex b def' -# str.push 'a\eacute x' -# str.push 'a\egrave x' -# str.push 'a\ediaeresis x' -# str.push 'a\ediaeresis' -# str.push '\aeligature xx' -# str.push '+abc' -# str.push 'ijs' -# str.push 'ijverig' -# str.push '\ijligature verig' -# str.push 'ypsilon' - -# old = str.dup - -# str.collect! do |s| - # sorter.remap(s) -# end - -# str.sort.each do |i| - # puts i -# end - diff --git a/scripts/context/ruby/texmfstart.rb b/scripts/context/ruby/texmfstart.rb index c082b623d..d791ee1a4 100644 --- a/scripts/context/ruby/texmfstart.rb +++ b/scripts/context/ruby/texmfstart.rb @@ -361,7 +361,7 @@ def output(str) end def usage - print "version : #{$version} - 2003/2004 - www.pragma-ade.com\n" + print "version : #{$version} - 2003/2005 - www.pragma-ade.com\n" print("\n") print("usage : texmfstart [switches] filename [optional arguments]\n") print("\n") -- cgit v1.2.3