diff options
Diffstat (limited to 'Master/texmf-dist/scripts/context/ruby/ctxtools.rb')
-rw-r--r-- | Master/texmf-dist/scripts/context/ruby/ctxtools.rb | 1251 |
1 files changed, 1156 insertions, 95 deletions
diff --git a/Master/texmf-dist/scripts/context/ruby/ctxtools.rb b/Master/texmf-dist/scripts/context/ruby/ctxtools.rb index 94e6e735a20..0cf96e10d70 100644 --- a/Master/texmf-dist/scripts/context/ruby/ctxtools.rb +++ b/Master/texmf-dist/scripts/context/ruby/ctxtools.rb @@ -15,9 +15,38 @@ # todo: move scite here # -# todo: move kpse call to kpse class/module +# todo: move kpse call to kpse class/module, faster and better -banner = ['CtxTools', 'version 1.2.2', '2004/2005', 'PRAGMA ADE/POD'] +# Taco Hoekwater on patterns and lig building (see 'agr'): +# +# Any direct use of a ligature (as accessed by \char or through active +# characters) is wrong and will create faulty hyphenation. Normally, +# when TeX sees "office", it has six tokens, and it knows from the +# patterns that it can hyphenate between the "ff". It will build an +# internal list of four nodes, like this: +# +# [char, o , ffi ] +# [lig , ffi, c ,[f,f,i]] +# [char, c , e ] +# [char, e , NULL] +# +# as you can see from the ffi line, it has remembered the original +# characters. While hyphenating, it temporarily changes back to +# that, then re-instates the ligature afterwards. +# +# If you feed it the ligature directly, like so: +# +# [char, o , ffi ] +# [char, ffi , c ] +# [char, c , e ] +# [char, e , NULL] +# +# it cannot do that (it tries to hyphenate as if the "ffi" was a +# character), and the result is wrong hyphenation. + +banner = ['CtxTools', 'version 1.3.3', '2004/2006', 'PRAGMA ADE/POD'] + +# todo dirname unless defined? ownpath ownpath = $0.sub(/[\\\/][a-z0-9\-]*?\.rb/i,'') @@ -29,6 +58,7 @@ require 'base/logger' require 'base/system' require 'rexml/document' +require 'net/http' require 'ftools' require 'kconv' @@ -84,24 +114,32 @@ class Commands end end unless maincontextfile.empty? then + nextcontextfile = maincontextfile.sub(/context\.tex$/,"cont-new.tex") case action - when 1 then touchfile(maincontextfile) - when 2 then reportversion(maincontextfile) + when 1 then + touchfile(maincontextfile) + touchfile(nextcontextfile,@@newcontextversion) + when 2 then + reportversion(maincontextfile) + reportversion(nextcontextfile,@@newcontextversion) end end end - def touchfile(filename) + @@contextversion = "\\\\contextversion" + @@newcontextversion = "\\\\newcontextversion" + + def touchfile(filename,command=@@contextversion) if FileTest.file?(filename) then if data = IO.read(filename) then - timestamp = Time.now.strftime('%Y.%m.%d') + timestamp = Time.now.strftime('%Y.%m.%d %H:%M') prevstamp = '' begin - data.gsub!(/\\contextversion\{(\d+\.\d+\.\d+)\}/) do + data.gsub!(/#{command}\{(\d+\.\d+\.\d+.*?)\}/) do prevstamp = $1 - "\\contextversion{#{timestamp}}" + "#{command.sub(/(\\)+/,"\\")}{#{timestamp}}" end rescue else @@ -133,11 +171,11 @@ class Commands end - def reportversion(filename) + def reportversion(filename,command=@@contextversion) version = 'unknown' begin - if FileTest.file?(filename) && IO.read(filename).match(/\\contextversion\{(\d+\.\d+\.\d+)\}/) then + if FileTest.file?(filename) && IO.read(filename).match(/#{command}\{(\d+\.\d+\.\d+.*?)\}/) then version = $1 end rescue @@ -145,7 +183,7 @@ class Commands if @commandline.option("pipe") then print version else - report("context version: #{version}") + report("context version: #{version} (#{filename})") end end @@ -183,7 +221,7 @@ class Commands interfaces = @commandline.arguments if interfaces.empty? then - interfaces = ['en', 'cz','de','it','nl','ro'] + interfaces = ['en','cz','de','it','nl','ro','fr'] end interfaces.each do |interface| @@ -281,7 +319,7 @@ class Commands interfaces = @commandline.arguments if interfaces.empty? then - interfaces = ['cz','de','it','nl','ro'] + interfaces = ['cz','de','it','nl','ro','fr'] else interfaces.delete('en') end @@ -353,6 +391,10 @@ class Commands data.i_translate('cd:inherit' , 'name' , strings) # data.i_translate('cd:command' , 'name' , strings) + data.gsub!(/(\<cd\:interface[^\>]*?language=")en(")/) do + $1 + interface + $2 + end + report("saving #{outfile}") begin @@ -375,13 +417,19 @@ class Commands public - def purgefiles(all=false) + def purgefiles pattern = @commandline.arguments - purgeall = @commandline.option("all") || all + purgeall = @commandline.option("all") recurse = @commandline.option("recurse") $dontaskprefixes.push(Dir.glob("mpx-*")) + + if purgeall then + $dontaskprefixes.push(Dir.glob("*.tex.prep")) + $dontaskprefixes.push(Dir.glob("*.xml.prep")) + end + $dontaskprefixes.flatten! $dontaskprefixes.sort! @@ -394,7 +442,7 @@ class Commands if ! pattern || pattern.empty? then globbed = if recurse then "**/*.*" else "*.*" end files = Dir.glob(globbed) - report("purging files : #{globbed}") + report("purging#{if purgeall then ' all' end} temporary files : #{globbed}") else pattern.each do |pat| globbed = if recurse then "**/#{pat}-*.*" else "#{pat}-*.*" end @@ -402,7 +450,7 @@ class Commands globbed = if recurse then "**/#{pat}.*" else "#{pat}.*" end files.push(Dir.glob(globbed)) end - report("purging files : #{pattern.join(' ')}") + report("purging#{if purgeall then ' all' end} temporary files : #{pattern.join(' ')}") end files.flatten! files.sort! @@ -428,6 +476,9 @@ class Commands end end end + $dummyfiles.each do |file| + (File.delete(file) if (FileTest.size?(file) rescue 10) < 10) rescue false + end $texnonesuffixes.each do |suffix| files.each do |file| if file =~ /(.*)\.#{suffix}$/i then @@ -461,10 +512,6 @@ class Commands end - def purgeallfiles - purgefiles(true) # for old times sake - end - private $removedfiles = 0 @@ -486,7 +533,9 @@ class Commands $forsuresuffixes = [ "tui", "tup", "ted", "tes", "top", "log", "tmp", "run", "bck", "rlg", - "mpt", "mpx", "mpd", "mpo" + "mpt", "mpx", "mpd", "mpo", "mpb", + "ctl", + "tmp.md5", "tmp.out" ] $texonlysuffixes = [ "dvi", "ps", "pdf" @@ -494,6 +543,9 @@ class Commands $texnonesuffixes = [ "tuo", "tub", "top" ] + $dummyfiles = [ + "mpgraph" + ] def removecontextfile (filename) if filename && FileTest.file?(filename) then @@ -607,7 +659,7 @@ class Commands str.chomp! str.sub!(/\s*$/o, '') case str - when /^[%\#]D/io then + when /^[%\#]D($| )/io then if skiplevel == 0 then someline = if str.length < 3 then "" else str[3,str.length-1] end if indocument then @@ -625,7 +677,7 @@ class Commands nofdocuments += 1 end end - when /^[%\#]M/io then + when /^[%\#]M($| )/io then if skiplevel == 0 then someline = if str.length < 3 then "" else str[3,str.length-1] end ted.puts("#{someline}\n") @@ -642,20 +694,25 @@ class Commands else if skiplevel == 0 then inlocaldocument = indocument + inlocaldocument = false # else first line skipped when not empty someline = str if indocument then ted.puts("\\stopdocumentation\n") indocument = false end - if someline.empty? && indefinition then - ted.puts("\\stopdefinition\n") - indefinition = false - elsif indefinition then - ted.puts("#{someline}\n") + if indefinition then + if someline.empty? then + ted.puts("\\stopdefinition\n") + indefinition = false + else + ted.puts("#{someline}\n") + end elsif ! someline.empty? then ted.puts("\n\\startdefinition\n") indefinition = true - unless inlocaldocument then + if inlocaldocument then + # nothing + else nofdefinitions += 1 ted.puts("#{someline}\n") end @@ -742,6 +799,56 @@ end # # Maybe I'll make this hyptools.tex +class String + + def markbraces + level = 0 + self.gsub(/([\{\}])/o) do |chr| + if chr == '{' then + level = level + 1 + chr = "((+#{level}))" + elsif chr == '}' then + chr = "((-#{level}))" + level = level - 1 + end + chr + end + end + + def unmarkbraces + self.gsub(/\(\(\+\d+?\)\)/o) do + "{" + end .gsub(/\(\(\-\d+?\)\)/o) do + "}" + end + end + + def getargument(pattern) + if self =~ /(#{pattern})\s*\(\(\+(\d+)\)\)(.*?)\(\(\-\2\)\)/m then # no /o + return $3 + else + return "" + end + end + + def withargument(pattern, &block) + if self.markbraces =~ /^(.*)(#{pattern}\s*)\(\(\+(\d+)\)\)(.*?)\(\(\-\3\)\)(.*)$/m then # no /o + "#{$1.unmarkbraces}#{$2}{#{yield($4.unmarkbraces)}}#{$5.unmarkbraces}" + else + self + end + end + + def filterargument(pattern, &block) + if self.markbraces =~ /^(.*)(#{pattern}\s*)\(\(\+(\d+)\)\)(.*?)\(\(\-\3\)\)(.*)$/m then # no /o + yield($4.unmarkbraces) + else + self + end + end + +end + class Language include CommandBase @@ -751,6 +858,7 @@ class Language @language = language @filenames = filenames @remapping = Array.new + @demapping = Array.new @unicode = Hash.new @encoding = encoding @data = '' @@ -758,8 +866,11 @@ class Language 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') + when 't1', 'ec', 'cork' then preload_vector('ec', 'enco-ec.tex') + when 'y', 'texnansi' then preload_vector('texnansi', 'enco-ans.tex') + when 'agr', 'agreek' then preload_vector('agr', 'enco-agr.tex') + when 't2a' then preload_vector('t2a', 'enco-cyr.tex') + when 'cyr' then preload_vector() # somehow loading t2a does not work out well end end @@ -774,6 +885,9 @@ class Language def remap(from, to) @remapping.push([from,to]) end + def demap(from, to) + @demapping.push([from,to]) + end def load(filenames=@filenames) begin @@ -783,10 +897,11 @@ class Language begin if fname = located(filename) then data = IO.read(fname) - @data += data.gsub(/\%.*$/, '') + @data += data.gsub(/\%.*$/, '').gsub(/\\message\{.*?\}/, '') data.gsub!(/(\\patterns|\\hyphenation)\s*\{.*/mo) do '' end @read += "\n% preamble of file #{fname}\n\n#{data}\n" report("file #{fname} is loaded") + @data.gsub!(/^[\s\n]+$/mois, '') break # next fileset end rescue @@ -806,11 +921,45 @@ class Language def convert if @data then n = 0 - @remapping.each do |k| - @data.gsub!(k[0]) do - # report("#{k[0]} => #{k[1]}") - n += 1 - k[1] + if true then + report("") + ["\\patterns","\\hyphenation"].each do |what| + @data = @data.withargument(what) do |content| + report("converting #{what}") + report("") + @demapping.each_index do |i| + content.gsub!(@demapping[i][0], @demapping[i][1]) + end + content.gsub!(/\\delete\{.*?\}/o) do '' end + content.gsub!(/\\keep\{(.*?)\}/o) do $1 end + done = false + @remapping.each_index do |i| + from, to, m = @remapping[i][0], @remapping[i][1], 0 + content.gsub!(from) do + done = true + m += 1 + "[#{i}]" + end + report("#{m.to_s.rjust(5)} entries remapped to #{to}") unless m == 0 + n += m + end + content.gsub!(/\[(\d+)\]/o) do + @remapping[$1.to_i][1] + end + report(" nothing remapped") unless done + report("") + content.to_s + end + end + else + @remapping.each do |k| + from, to, m = k[0], k[1], 0 + @data.gsub!(from) do + m += 1 + to + end + report("#{m.to_s.rjust(5)} entries remapped to #{to}") unless m == 0 + n += m end end report("#{n} changes in patterns and exceptions") @@ -865,6 +1014,7 @@ class Language end def triggerunicode + return 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" + @@ -963,9 +1113,9 @@ class Language begin if f = File.open(patname,'w') then data = '' - @data.scan(/\\patterns\s*\{\s*(.*?)\s*\}/m) do + @data.filterargument('\\patterns') do |content| report("merging patterns") - data += $1 + "\n" + data += content.strip end data.gsub!(/(\s*\n\s*)+/mo, "\n") @@ -989,9 +1139,9 @@ class Language begin if f = File.open(hypname,'w') then data = '' - @data.scan(/\\hyphenation\s*\{\s*(.*?)\s*\}/m) do + @data.filterargument('\\hyphenation') do |content| report("merging exceptions") - data += $1 + "\n" + data += content.strip end data.gsub!(/(\s*\n\s*)+/mo, "\n") f << banner @@ -1094,7 +1244,7 @@ class Language end - def preload_vector(encoding='') + def preload_vector(encoding='', filename='') # funny polish @@ -1117,41 +1267,285 @@ class Language remap(/X/, "[aeligature]") remap(/Y/, "[ostroke]") remap(/Z/, "[aring]") + when 'hu' then + # nothing when 'ca' then - remap(/\\c\{.*?\}/, "") + demap(/\\c\{/, "\\delete{") when 'de', 'deo' then - remap(/\\c\{.*?\}/, "") - remap(/\\n\{\}/, "") + demap(/\\c\{/, "\\delete{") + demap(/\\n\{/, "\\keep{") remap(/\\3/, "[ssharp]") remap(/\\9/, "[ssharp]") remap(/\"a/, "[adiaeresis]") remap(/\"o/, "[odiaeresis]") remap(/\"u/, "[udiaeresis]") when 'fr' then + demap(/\\n\{/, "\\keep{") remap(/\\ae/, "[adiaeresis]") remap(/\\oe/, "[odiaeresis]") when 'la' then # \lccode`'=`' somewhere else, todo - remap(/\\c\{.*?\}/, "") + demap(/\\c\{/, "\\delete{") remap(/\\a\s*/, "[aeligature]") remap(/\\o\s*/, "[oeligature]") + when 'agr' then + remap(/\<\'a\|/, "[greekalphaiotasubdasiatonos]") + # remap(/\<\'a\|/, "[greekdasiatonos][greekAlpha][greekiota]") + remap(/\>\'a\|/, "[greekalphaiotasubpsilitonos]") + remap(/\<\`a\|/, "[greekalphaiotasubdasiavaria]") + remap(/\>\`a\|/, "[greekalphaiotasubpsilivaria]") + remap(/\<\~a\|/, "[greekalphaiotasubdasiaperispomeni]") + remap(/\>\~a\|/, "[greekalphaiotasubpsiliperispomeni]") + remap(/\'a\|/, "[greekalphaiotasubtonos]") + remap(/\`a\|/, "[greekalphaiotasubvaria]") + remap(/\~a\|/, "[greekalphaiotasubperispomeni]") + remap(/\<a\|/, "[greekalphaiotasubdasia]") + remap(/\>a\|/, "[greekalphaiotasubpsili]") + remap(/a\|/, "[greekalphaiotasub]") + remap(/\<\'h\|/, "[greeketaiotasubdasiatonos]") + remap(/\>\'h\|/, "[greeketaiotasubpsilitonos]") + remap(/\<\`h\|/, "[greeketaiotasubdasiavaria]") + remap(/\>\`h\|/, "[greeketaiotasubpsilivaria]") + remap(/\<\~h\|/, "[greeketaiotasubdasiaperispomeni]") + remap(/\>\~h\|/, "[greeketaiotasubpsiliperispomeni]") + remap(/\'h\|/, "[greeketaiotasubtonos]") + remap(/\`h\|/, "[greeketaiotasubvaria]") + remap(/\~h\|/, "[greeketaiotasubperispomeni]") + remap(/\<h\|/, "[greeketaiotasubdasia]") + remap(/\>h\|/, "[greeketaiotasubpsili]") + remap(/h\|/, "[greeketaiotasub]") + remap(/\<'w\|/, "[greekomegaiotasubdasiatonos]") + remap(/\>'w\|/, "[greekomegaiotasubpsilitonos]") + remap(/\<`w\|/, "[greekomegaiotasubdasiavaria]") + remap(/\>`w\|/, "[greekomegaiotasubpsilivaria]") + remap(/\<~w\|/, "[greekomegaiotasubdasiaperispomeni]") + remap(/\>~w\|/, "[greekomegaiotasubpsiliperispomeni]") + remap(/\<w\|/, "[greekomegaiotasubdasia]") + remap(/\>w\|/, "[greekomegaiotasubpsili]") + remap(/\'w\|/, "[greekomegaiotasubtonos]") + remap(/\`w\|/, "[greekomegaiotasubvaria]") + remap(/\~w\|/, "[greekomegaiotasubperispomeni]") + remap(/w\|/, "[greekomegaiotasub]") + remap(/\<\'i/, "[greekiotadasiatonos]") + remap(/\>\'i/, "[greekiotapsilitonos]") + remap(/\<\`i/, "[greekiotadasiavaria]") + remap(/\>\`i/, "[greekiotapsilivaria]") + remap(/\<\~i/, "[greekiotadasiaperispomeni]") + remap(/\>\~i/, "[greekiotapsiliperispomeni]") + remap(/\"\'i/, "[greekiotadialytikatonos]") + remap(/\"\`i/, "[greekiotadialytikavaria]") + remap(/\"\~i/, "[greekiotadialytikaperispomeni]") + remap(/\<i/, "[greekiotadasia]") + remap(/\>i/, "[greekiotapsili]") + remap(/\'i/, "[greekiotaoxia]") + remap(/\`i/, "[greekiotavaria]") + remap(/\~i/, "[greekiotaperispomeni]") + remap(/\"i/, "[greekiotadialytika]") + remap(/\>\~e/, "[greekepsilonpsiliperispomeni]") + remap(/\<\~e/, "[greekepsilondasiaperispomeni]") + remap(/\<\'e/, "[greekepsilondasiatonos]") + remap(/\>\'e/, "[greekepsilonpsilitonos]") + remap(/\<\`e/, "[greekepsilondasiavaria]") + remap(/\>\`e/, "[greekepsilonpsilivaria]") + remap(/\<e/, "[greekepsilondasia]") + remap(/\>e/, "[greekepsilonpsili]") + remap(/\'e/, "[greekepsilonoxia]") + remap(/\`e/, "[greekepsilonvaria]") + remap(/\~e/, "[greekepsilonperispomeni]") + remap(/\<\'a/, "[greekalphadasiatonos]") + remap(/\>\'a/, "[greekalphapsilitonos]") + remap(/\<\`a/, "[greekalphadasiavaria]") + remap(/\>\`a/, "[greekalphapsilivaria]") + remap(/\<\~a/, "[greekalphadasiaperispomeni]") + remap(/\>\~a/, "[greekalphapsiliperispomeni]") + remap(/\<a/, "[greekalphadasia]") + remap(/\>a/, "[greekalphapsili]") + remap(/\'a/, "[greekalphaoxia]") + remap(/\`a/, "[greekalphavaria]") + remap(/\~a/, "[greekalphaperispomeni]") + remap(/\<\'h/, "[greeketadasiatonos]") + remap(/\>\'h/, "[greeketapsilitonos]") + remap(/\<\`h/, "[greeketadasiavaria]") + remap(/\>\`h/, "[greeketapsilivaria]") + remap(/\<\~h/, "[greeketadasiaperispomeni]") + remap(/\>\~h/, "[greeketapsiliperispomeni]") + remap(/\<h/, "[greeketadasia]") + remap(/\>h/, "[greeketapsili]") + remap(/\'h/, "[greeketaoxia]") + remap(/\`h/, "[greeketavaria]") + remap(/\~h/, "[greeketaperispomeni]") + remap(/\<\~o/, "[greekomicrondasiaperispomeni]") + remap(/\>\~o/, "[greekomicronpsiliperispomeni]") + remap(/\<\'o/, "[greekomicrondasiatonos]") + remap(/\>\'o/, "[greekomicronpsilitonos]") + remap(/\<\`o/, "[greekomicrondasiavaria]") + remap(/\>\`o/, "[greekomicronpsilivaria]") + remap(/\<o/, "[greekomicrondasia]") + remap(/\>o/, "[greekomicronpsili]") + remap(/\'o/, "[greekomicronoxia]") + remap(/\`o/, "[greekomicronvaria]") + remap(/\~o/, "[greekomicronperispomeni]") + remap(/\<\'u/, "[greekupsilondasiatonos]") + remap(/\>\'u/, "[greekupsilonpsilitonos]") + remap(/\<\`u/, "[greekupsilondasiavaria]") + remap(/\>\'u/, "[greekupsilonpsilivaria]") + remap(/\<\~u/, "[greekupsilondasiaperispomeni]") + remap(/\>\~u/, "[greekupsilonpsiliperispomeni]") + remap(/\"\'u/, "[greekupsilondialytikatonos]") + remap(/\"\`u/, "[greekupsilondialytikavaria]") + remap(/\"\~u/, "[greekupsilondialytikaperispomeni]") + remap(/\<u/, "[greekupsilondasia]") + remap(/\>u/, "[greekupsilonpsili]") + remap(/\'u/, "[greekupsilonoxia]") + remap(/\`u/, "[greekupsilonvaria]") + remap(/\~u/, "[greekupsilonperispomeni]") + remap(/\"u/, "[greekupsilondiaeresis]") + remap(/\<\'w/, "[greekomegadasiatonos]") + remap(/\>\'w/, "[greekomegapsilitonos]") + remap(/\<\`w/, "[greekomegadasiavaria]") + remap(/\>\`w/, "[greekomegapsilivaria]") + remap(/\<\~w/, "[greekomegadasiaperispomeni]") + remap(/\>\~w/, "[greekomegapsiliperispomeni]") + remap(/\<w/, "[greekomegadasia]") + remap(/\>w/, "[greekomegapsili]") + remap(/\'w/, "[greekomegaoxia]") + remap(/\`w/, "[greekomegavaria]") + remap(/\~w/, "[greekomegaperispomeni]") + remap(/\<r/, "[greekrhodasia]") + remap(/\>r/, "[greekrhopsili]") + remap(/\<\~/, "[greekdasiaperispomeni]") + remap(/\>\~/, "[greekpsiliperispomeni]") + remap(/\<\'/, "[greekdasiatonos]") + remap(/\>\'/, "[greekpsilitonos]") + remap(/\<\`/, "[greekdasiavaria]") + remap(/\>\`/, "[greekpsilivaria]") + remap(/\"\'/, "[greekdialytikatonos]") + remap(/\"\`/, "[greekdialytikavaria]") + remap(/\"\~/, "[greekdialytikaperispomeni]") + remap(/\</, "[dasia]") + remap(/\>/, "[psili]") + remap(/\'/, "[oxia]") + remap(/\`/, "[greekvaria]") + remap(/\~/, "[perispomeni]") + remap(/\"/, "[dialytika]") + # unknown + remap(/\|/, "[greekIotadialytika]") + # next + remap(/A/, "[greekAlpha]") + remap(/B/, "[greekBeta]") + remap(/D/, "[greekDelta]") + remap(/E/, "[greekEpsilon]") + remap(/F/, "[greekPhi]") + remap(/G/, "[greekGamma]") + remap(/H/, "[greekEta]") + remap(/I/, "[greekIota]") + remap(/J/, "[greekTheta]") + remap(/K/, "[greekKappa]") + remap(/L/, "[greekLambda]") + remap(/M/, "[greekMu]") + remap(/N/, "[greekNu]") + remap(/O/, "[greekOmicron]") + remap(/P/, "[greekPi]") + remap(/Q/, "[greekChi]") + remap(/R/, "[greekRho]") + remap(/S/, "[greekSigma]") + remap(/T/, "[greekTau]") + remap(/U/, "[greekUpsilon]") + remap(/W/, "[greekOmega]") + remap(/X/, "[greekXi]") + remap(/Y/, "[greekPsi]") + remap(/Z/, "[greekZeta]") + remap(/a/, "[greekalpha]") + remap(/b/, "[greekbeta]") + remap(/c/, "[greekfinalsigma]") + remap(/d/, "[greekdelta]") + remap(/e/, "[greekepsilon]") + remap(/f/, "[greekphi]") + remap(/g/, "[greekgamma]") + remap(/h/, "[greeketa]") + remap(/i/, "[greekiota]") + remap(/j/, "[greektheta]") + remap(/k/, "[greekkappa]") + remap(/l/, "[greeklambda]") + remap(/m/, "[greekmu]") + remap(/n/, "[greeknu]") + remap(/o/, "[greekomicron]") + remap(/p/, "[greekpi]") + remap(/q/, "[greekchi]") + remap(/r/, "[greekrho]") + remap(/s/, "[greeksigma]") + remap(/t/, "[greektau]") + remap(/u/, "[greekupsilon]") + remap(/w/, "[greekomega]") + remap(/x/, "[greekxi]") + remap(/y/, "[greekpsi]") + remap(/z/, "[greekzeta]") + when 'ru' then + remap(/\xC1/, "[cyrillica]") + remap(/\xC2/, "[cyrillicb]") + remap(/\xD7/, "[cyrillicv]") + remap(/\xC7/, "[cyrillicg]") + remap(/\xC4/, "[cyrillicd]") + remap(/\xC5/, "[cyrillice]") + remap(/\xD6/, "[cyrilliczh]") + remap(/\xDA/, "[cyrillicz]") + remap(/\xC9/, "[cyrillici]") + remap(/\xCA/, "[cyrillicishrt]") + remap(/\xCB/, "[cyrillick]") + remap(/\xCC/, "[cyrillicl]") + remap(/\xCD/, "[cyrillicm]") + remap(/\xCE/, "[cyrillicn]") + remap(/\xCF/, "[cyrillico]") + remap(/\xD0/, "[cyrillicp]") + remap(/\xD2/, "[cyrillicr]") + remap(/\xD3/, "[cyrillics]") + remap(/\xD4/, "[cyrillict]") + remap(/\xD5/, "[cyrillicu]") + remap(/\xC6/, "[cyrillicf]") + remap(/\xC8/, "[cyrillich]") + remap(/\xC3/, "[cyrillicc]") + remap(/\xDE/, "[cyrillicch]") + remap(/\xDB/, "[cyrillicsh]") + remap(/\xDD/, "[cyrillicshch]") + remap(/\xDF/, "[cyrillichrdsn]") + remap(/\xD9/, "[cyrillicery]") + remap(/\xD8/, "[cyrillicsftsn]") + remap(/\xDC/, "[cyrillicerev]") + remap(/\xC0/, "[cyrillicyu]") + remap(/\xD1/, "[cyrillicya]") + remap(/\xA3/, "[cyrillicyo]") else end if ! encoding.empty? then begin - filename = `kpsewhich -progname=context enco-#{encoding}.tex` - if data = IO.read(filename.chomp) then + filename = `kpsewhich -progname=context #{filename}` + if data = IO.readlines(filename.chomp) then report("preloading #{encoding} character mappings") - data.scan(/\\definecharacter\s*([a-zA-Z]+)\s*(\d+)\s*/o) do - name, number = $1, $2 - remap(/\^\^#{sprintf("%02x",number)}/, "[#{name}]") + accept = false + data.each do |line| + case line.chomp + when /\\start(en|)coding\s*\[(.*?)\]/io then + enc = $2 + if accept = (enc == encoding) then + report("accepting vector #{enc}") + else + report("skipping vector #{enc}") + end + when /\\stop(en|)coding/io then + accept = false + when accept && /\\definecharacter\s*([a-zA-Z]+)\s*(\d+)\s*/o then + name, number = $1, $2 + remap(/\^\^#{sprintf("%02x",number)}/, "[#{name}]") + if number.to_i > 127 then + remap(/#{sprintf("\\%03o",number)}/, "[#{name}]") + end + end end end rescue end end - end end @@ -1185,7 +1579,7 @@ class Commands # todo: filter the fallback list from context # The first entry in the array is the encoding which will be used - # when interpreting th eraw patterns. The second entry is a list of + # when interpreting the raw patterns. The second entry is a list of # filesets (string|aray), each first match of a set is taken. @@languagedata['ba' ] = [ 'ec' , ['bahyph.tex'] ] @@ -1204,6 +1598,7 @@ class Commands @@languagedata['hr' ] = [ 'ec' , ['hrhyph.tex'] ] @@languagedata['hu' ] = [ 'ec' , ['huhyphn.tex'] ] @@languagedata['en' ] = [ 'default' , [['ushyphmax.tex','ushyph.tex','hyphen.tex']] ] + @@languagedata['us' ] = [ 'default' , [['ushyphmax.tex','ushyph.tex','hyphen.tex']] ] # inhyph.tex @@languagedata['is' ] = [ 'ec' , ['ishyph.tex'] ] @@languagedata['it' ] = [ 'ec' , ['ithyph.tex'] ] @@ -1211,7 +1606,7 @@ class Commands # mnhyph @@languagedata['nl' ] = [ 'ec' , ['nehyph96.tex'] ] @@languagedata['no' ] = [ 'ec' , ['nohyph.tex'] ] - # oldgrhyph.tex + @@languagedata['agr'] = [ 'agr' , [['grahyph4.tex','oldgrhyph.tex']] ] # new, todo @@languagedata['pl' ] = [ 'ec' , ['plhyph.tex'] ] @@languagedata['pt' ] = [ 'ec' , ['pthyph.tex'] ] @@languagedata['ro' ] = [ 'ec' , ['rohyph.tex'] ] @@ -1222,7 +1617,8 @@ class Commands @@languagedata['sv' ] = [ 'ec' , ['svhyph.tex'] ] @@languagedata['tr' ] = [ 'ec' , ['tkhyph.tex'] ] @@languagedata['uk' ] = [ 'default' , [['ukhyphen.tex','ukhyph.tex']] ] - + # @@languagedata['ru' ] = [ 't2a' , ['ruhyphal.tex'] ] # t2a does not work + @@languagedata['ru' ] = [ 'cyr' , ['ruhyphal.tex'] ] end class Commands @@ -1235,10 +1631,11 @@ class Commands texmfroot = @commandline.argument('first') texmfroot = '.' if texmfroot.empty? - maproot = "#{texmfroot}/fonts/map/pdftex/context" + maproot = "#{texmfroot.gsub(/\\/,'/')}/fonts/map/pdftex/context" if File.directory?(maproot) then - if files = Dir.glob("#{maproot}/*.map") and files.size > 0 then + files = Dir.glob("#{maproot}/*.map") + if files.size > 0 then files.each do |pdffile| next if File.basename(pdffile) == 'pdftex.map' pdffile = File.expand_path(pdffile) @@ -1267,6 +1664,12 @@ class Commands data.delete_if do |line| line.gsub(/\s+/,'').empty? end + data.collect! do |line| + # remove line with "name name" lines + line.gsub(/^(\S+)\s+\1\s*$/) do + $1 + end + end begin if force then if n > 0 then @@ -1279,8 +1682,12 @@ class Commands report("? #{File.basename(dpxfile)} - dvipdfm(x)") end else - report("- #{File.basename(dpxfile)} - dvipdfm(x)") - begin File.delete(dpxname) ; rescue ; end + report("- #{File.basename(dpxfile)} - dvipdfm(x) - no entries") + # begin File.delete(dpxname) ; rescue ; end + if f = File.open(dpxfile,'w') then + f.puts("% no map entries") + f.close + end end else report(". #{File.basename(dpxfile)} - dvipdfm(x) - #{n}") @@ -1314,6 +1721,118 @@ class Commands end +class Array + + def add_shebang(filename,program) + unless self[0] =~ /^\#/ then + self.insert(0,"\#!/usr/env #{program}") + end + unless self[2] =~ /^\#.*?copyright\=/ then + self.insert(1,"\#") + self.insert(2,"\# copyright=pragma-ade readme=readme.pdf licence=cc-gpl") + self.insert(3,"") unless self[3].chomp.strip.empty? + self[2].gsub!(/ +/, ' ') + return true + else + return false + end + end + + def add_directive(filename,program) + unless self[0] =~ /^\%/ then + self.insert(0,"\% content=#{program}") + end + unless self[2] =~ /^\%.*?copyright\=/ then + self.insert(1,"\%") + if File.expand_path(filename) =~ /[\\\/](doc|manuals)[\\\/]/ then + self.insert(2,"\% copyright=pragma-ade readme=readme.pdf licence=cc-by-nc-sa") + else + self.insert(2,"\% copyright=pragma-ade readme=readme.pdf licence=cc-gpl") + end + self.insert(3,"") unless self[3].chomp.strip.empty? + self[0].gsub!(/ +/, ' ') + return true + else + return false + end + end + + def add_comment(filename) + if self[0] =~ /<\?xml.*?\?>/ && self[2] !~ /^<\!\-\-.*?copyright\=.*?\-\->/ then + self.insert(1,"") + if File.expand_path(filename) =~ /[\\\/](doc|manuals)[\\\/]/ then + self.insert(2,"<!-- copyright='pragma-ade' readme='readme.pdf' licence='cc-by-nc-sa' -->") + else + self.insert(2,"<!-- copyright='pragma-ade' readme='readme.pdf' licence='cc-gpl' -->") + end + self.insert(3,"") unless self[3].chomp.strip.empty? + return true + else + return false + end + end + +end + +class Commands + + include CommandBase + + def brandfiles + + force = @commandline.option("force") + files = @commandline.arguments # Dir.glob("**/*.*") + done = false + + files.each do |filename| + if FileTest.file?(filename) then + ok = false + begin + data = IO.readlines(filename) + case filename + when /\.rb$/ then + ok = data.add_shebang(filename,'ruby') + when /\.pl$/ then + ok = data.add_shebang(filename,'perl') + when /\.py$/ then + ok = data.add_shebang(filename,'python') + when /\.lua$/ then + ok = data.add_shebang(filename,'lua') + when /\.tex$/ then + ok = data.add_directive(filename,'tex') + when /\.mp$/ then + ok = data.add_directive(filename,'metapost') + when /\.mf$/ then + ok = data.add_directive(filename,'metafont') + when /\.(xml|xsl|fo|fx|rlx|rng|exa)$/ then + ok = data.add_comment(filename) + end + rescue + report("fatal error in processing #{filename}") # maybe this catches the mac problem taco reported + else + if ok then + report() + report(filename) + report() + for i in 0..4 do + report(' ' + data[i].chomp) + end + if force && f = File.open(filename,'w') then + f.puts data + f.close + end + done = true + end + end + else + report("no file named #{filename}") + end + end + report() if done + end + +end + class Commands include CommandBase @@ -1322,68 +1841,609 @@ class Commands # document: <!DOCTYPE something SYSTEM "entities.xml"> def flushentities(handle,entities,doctype=nil) # 'stylesheet' - tab = if doctype then "\t" else "" end - handle.puts("<!DOCTYPE #{doctype} [") if doctype + if doctype then + tab = "\t" + handle << "<?xml version='1.0' encoding='utf-8'?>\n\n" + handle << "<!-- !DOCTYPE entities SYSTEM 'entities.xml' -->\n\n" + handle << "<!DOCTYPE #{doctype} [\n" + else + tab = "" + end entities.keys.sort.each do |k| - handle.puts("#{tab}<!ENTITY #{k} \"\&\##{entities[k]};\">") + handle << "#{tab}<!ENTITY #{k} \"\&\#x#{entities[k]};\">\n" + end + if doctype then + handle << "]>\n" end - handle.puts("]>") if doctype end def listentities - # filename = `texmfstart tmftools.rb --progname=context enco-uc.tex`.chomp - filename = `kpsewhich --progname=context enco-uc.tex`.chomp + filenames = ['enco-uc.tex','contextnames.txt'] outputname = @commandline.argument('first') + doctype = @commandline.option('doctype') + entities = Hash.new + + filenames.each do |filename| + # filename = `texmfstart tmftools.rb --progname=context #{filename}`.chomp + filename = `kpsewhich --progname=context #{filename}`.chomp + if filename and not filename.empty? and FileTest.file?(filename) then + report("loading #{filename.gsub(/\\/,'/')}") unless outputname.empty? + IO.readlines(filename).each do |line| + case line + when /^[\#\%]/io then + # skip comment line + when /\\definecharacter\s+([a-z]+)\s+\{\\uchar\{*(\d+)\}*\{(\d+)\}\}/io then + name, code = $1, ($2.to_i*256 + $3.to_i).to_s + entities[name] = code.rjust(4,'0') unless entities.key?(name) + when /^([A-F0-9]+)\;([a-z][a-z]+)\;(.*?)\;(.*?)\s*$/io then + code, name, adobe, comment = $1, $2, $3, $4 + entities[name] = code.rjust(4,'0') unless entities.key?(name) + end + end + end + end + if outputname and not outputname.empty? then + if f = File.open(outputname,'w') then + report("saving #{entities.size} entities in #{outputname}") + flushentities(f,entities,doctype) + f.close + else + flushentities($stdout,entities,doctype) + end + else + flushentities($stdout,entities,doctype) + end + end + +end + +class Commands + + include CommandBase + + def platformize + + pattern = if @commandline.arguments.empty? then "*.{rb,pl,py}" else @commandline.arguments end + recurse = @commandline.option("recurse") + force = @commandline.option("force") + pattern = "#{if recurse then '**/' else '' end}#{pattern}" + Dir.glob(pattern).each do |file| + if File.file?(file) then + size = File.size(file) + data = IO.readlines(file) + if force then + if f = File.open(file,'w') + data.each do |line| + f.puts(line.chomp) + end + f.close + end + if File.size(file) == size then # not robust + report("file '#{file}' is unchanged") + else + report("file '#{file}' is platformized") + end + else + report("file '#{file}' is a candidate") + end + end + end + end - if filename and not filename.empty? and FileTest.file?(filename) then - entities = Hash.new - IO.readlines(filename).each do |line| - if line =~ /\\definecharacter\s+([a-zA-Z]+)\s+\{\\uchar\{*(\d+)\}*\{(\d+)\}\}/o then - name, low, high = $1, $2.to_i, $3.to_i - entities[name] = low*256 + high +end + +class TexDeps + + @@cs_tex = %q/ + above abovedisplayshortskip abovedisplayskip + abovewithdelims accent adjdemerits advance afterassignment + aftergroup atop atopwithdelims + badness baselineskip batchmode begingroup + belowdisplayshortskip belowdisplayskip binoppenalty botmark + box boxmaxdepth brokenpenalty + catcode char chardef cleaders closein closeout clubpenalty + copy count countdef cr crcr csname + day deadcycles def defaulthyphenchar defaultskewchar + delcode delimiter delimiterfactor delimeters + delimitershortfall delimeters dimen dimendef discretionary + displayindent displaylimits displaystyle + displaywidowpenalty displaywidth divide + doublehyphendemerits dp dump + edef else emergencystretch end endcsname endgroup endinput + endlinechar eqno errhelp errmessage errorcontextlines + errorstopmode escapechar everycr everydisplay everyhbox + everyjob everymath everypar everyvbox exhyphenpenalty + expandafter + fam fi finalhyphendemerits firstmark floatingpenalty font + fontdimen fontname futurelet + gdef global group globaldefs + halign hangafter hangindent hbadness hbox hfil horizontal + hfill horizontal hfilneg hfuzz hoffset holdinginserts hrule + hsize hskip hss horizontal ht hyphenation hyphenchar + hyphenpenalty hyphen + if ifcase ifcat ifdim ifeof iffalse ifhbox ifhmode ifinner + ifmmode ifnum ifodd iftrue ifvbox ifvmode ifvoid ifx + ignorespaces immediate indent input inputlineno input + insert insertpenalties interlinepenalty + jobname + kern + language lastbox lastkern lastpenalty lastskip lccode + leaders left lefthyphenmin leftskip leqno let limits + linepenalty line lineskip lineskiplimit long looseness + lower lowercase + mag mark mathaccent mathbin mathchar mathchardef mathchoice + mathclose mathcode mathinner mathop mathopen mathord + mathpunct mathrel mathsurround maxdeadcycles maxdepth + meaning medmuskip message mkern month moveleft moveright + mskip multiply muskip muskipdef + newlinechar noalign noboundary noexpand noindent nolimits + nonscript scriptscript nonstopmode nulldelimiterspace + nullfont number + omit openin openout or outer output outputpenalty over + overfullrule overline overwithdelims + pagedepth pagefilllstretch pagefillstretch pagefilstretch + pagegoal pageshrink pagestretch pagetotal par parfillskip + parindent parshape parskip patterns pausing penalty + postdisplaypenalty predisplaypenalty predisplaysize + pretolerance prevdepth prevgraf + radical raise read relax relpenalty right righthyphenmin + rightskip romannumeral + scriptfont scriptscriptfont scriptscriptstyle scriptspace + scriptstyle scrollmode setbox setlanguage sfcode shipout + show showbox showboxbreadth showboxdepth showlists showthe + skewchar skip skipdef spacefactor spaceskip span special + splitbotmark splitfirstmark splitmaxdepth splittopskip + string + tabskip textfont textstyle the thickmuskip thinmuskip time + toks toksdef tolerance topmark topskip tracingcommands + tracinglostchars tracingmacros tracingonline tracingoutput + tracingpages tracingparagraphs tracingrestores tracingstats + uccode uchyph underline unhbox unhcopy unkern unpenalty + unskip unvbox unvcopy uppercase + vadjust valign vbadness vbox vcenter vfil vfill vfilneg + vfuzz voffset vrule vsize vskip vsplit vss vtop + wd widowpenalty write + xdef xleaders xspaceskip + year + /.split + + @@cs_etex = %q/ + beginL beginR botmarks + clubpenalties currentgrouplevel currentgrouptype + currentifbranch currentiflevel currentiftype + detokenize dimexpr displaywidowpenalties + endL endR eTeXrevision eTeXversion everyeof + firstmarks fontchardp fontcharht fontcharic fontcharwd + glueexpr glueshrink glueshrinkorder gluestretch + gluestretchorder gluetomu + ifcsname ifdefined iffontchar interactionmode + interactionmode interlinepenalties + lastlinefit lastnodetype + marks topmarks middle muexpr mutoglue + numexpr + pagediscards parshapedimen parshapeindent parshapelength + predisplaydirection + savinghyphcodes savingvdiscards scantokens showgroups + showifs showtokens splitdiscards splitfirstmarks + TeXXeTstate tracingassigns tracinggroups tracingifs + tracingnesting tracingscantokens + unexpanded unless + widowpenalties + /.split + + @@cs_pdftex = %q/ + pdfadjustspacing pdfannot pdfavoidoverfull + pdfcatalog pdfcompresslevel + pdfdecimaldigits pdfdest pdfdestmargin + pdfendlink pdfendthread + pdffontattr pdffontexpand pdffontname pdffontobjnum pdffontsize + pdfhorigin + pdfimageresolution pdfincludechars pdfinfo + pdflastannot pdflastdemerits pdflastobj + pdflastvbreakpenalty pdflastxform pdflastximage + pdflastximagepages pdflastxpos pdflastypos + pdflinesnapx pdflinesnapy pdflinkmargin pdfliteral + pdfmapfile pdfmaxpenalty pdfminpenalty pdfmovechars + pdfnames + pdfobj pdfoptionpdfminorversion pdfoutline pdfoutput + pdfpageattr pdfpageheight pdfpageresources pdfpagesattr + pdfpagewidth pdfpkresolution pdfprotrudechars + pdfrefobj pdfrefxform pdfrefximage + pdfsavepos pdfsnaprefpoint pdfsnapx pdfsnapy pdfstartlink + pdfstartthread + pdftexrevision pdftexversion pdfthread pdfthreadmargin + pdfuniqueresname + pdfvorigin + pdfxform pdfximage + /.split + + @@cs_omega = %q/ + odelimiter omathaccent omathchar oradical omathchardef omathcode odelcode + leftghost rightghost + charwd charht chardp charit + localleftbox localrightbox + localinterlinepenalty localbrokenpenalty + pagedir bodydir pardir textdir mathdir + boxdir nextfakemath + pagewidth pageheight pagerightoffset pagebottomoffset + nullocp nullocplist ocp externalocp ocplist pushocplist popocplist clearocplists ocptracelevel + addbeforeocplist addafterocplist removebeforeocplist removeafterocplist + OmegaVersion + InputTranslation OutputTranslation DefaultInputTranslation DefaultOutputTranslation + noInputTranslation noOutputTranslation + InputMode OutputMode DefaultInputMode DefaultOutputMode + noInputMode noOutputMode noDefaultInputMode noDefaultOutputMode + /.split + + @@cs_plain = %q/ + TeX + bgroup egroup endgraf space empty null + newcount newdimen newskip newmuskip newbox newtoks newhelp newread newwrite newfam newlanguage newinsert newif + maxdimen magstephalf magstep + frenchspacing nonfrenchspacing normalbaselines obeylines obeyspaces raggedright ttraggedright + thinspace negthinspace enspace enskip quad qquad + smallskip medskip bigskip removelastskip topglue vglue hglue + break nobreak allowbreak filbreak goodbreak smallbreak medbreak bigbreak + line leftline rightline centerline rlap llap underbar strutbox strut + cases matrix pmatrix bordermatrix eqalign displaylines eqalignno leqalignno + pageno folio tracingall showhyphens fmtname fmtversion + hphantom vphantom phantom smash + /.split + + @@cs_eplain = %q/ + eTeX + newmarks grouptype interactionmode nodetype iftype + tracingall loggingall tracingnone + /.split + + # let's ignore \dimendef etc + + @@primitives_def = "def|edef|xdef|gdef|let|newcount|newdimen|newskip|newbox|newtoks|newmarks|chardef|mathchardef|newconditional" + + @@cs_global = [@@cs_tex,@@cs_etex,@@cs_pdftex,@@cs_omega].sort.flatten + @@types = [['invalid','*'],['okay','='],['forward','>'],['backward','<'],['unknown','?']] + + def initialize(logger=nil) + @cs_local = Hash.new + @cs_new = Hash.new + @cs_defd = Hash.new + @cs_used = Hash.new + @filename = 'context.tex' + @files = Array.new # keep load order ! + @compact = false + @logger = logger + end + + def load(filename='context.tex',omitlist=['mult-com.tex']) + begin + @filename = filename + File.open(filename) do |f| + f.each do |line| + if line =~ /^\\input\s+(\S+)\s*/o then + @files.push($1) unless omitlist.include?(File.basename($1)) + end end end - if outputname and not outputname.empty? then - if f = File.open(outputname,'w') then - flushentities(f,entities) - f.close + rescue + @files = Array.new + end + end + + def analyze + @files.each do |filename| + if f = File.open(filename) then + @logger.report("loading #{filename}") if @logger + defs, uses, n = 0, 0, 0 + f.each do |line| + n += 1 + case line + when /^%/ + # skip + when /\\newif\s*\\if([a-zA-Z@\?\!]+)/ then + pushdef(filename,n,"if:#{$1}") + when /\\([a-zA-Z@\?\!]+)(true|false)/ then + pushuse(filename,n,"if:#{$1}") + when /^\s*\\(#{@primitives_def})\\([a-zA-Z@\?\!]{3,})/o + pushdef(filename,n,$2) + when /\\([a-zA-Z@\?\!]{3,})/o + pushuse(filename,n,$1) + end + end + f.close + end + end + end + + def feedback(compact=false) + begin + outputfile = File.basename(@filename).sub(/\.tex$/,'')+'.dep' + File.open(outputfile,'w') do |f| + @compact = compact + @logger.report("saving analysis in #{outputfile}") if @logger + list, len = @cs_local.keys.sort, 0 + if @compact then + list.each do |cs| + if cs.length > len then len = cs.length end + end + len += 1 else - flushentities($stdout,entities) + f.puts "<?xml version='1.0'?>\n" + f.puts "<dependencies xmlns='http://www.pragma-ade.com/schemas/texdeps.rng' rootfile='#{@filename}'>\n" + end + list.each do |cs| + if @cs_new.key?(cs) then + if @cs_new[cs] == @cs_local[cs] then + f.puts some_struc(cs,len,1,some_str(@cs_new,@cs_defd,cs)) + elsif @cs_new[cs].first == @cs_local[cs].first then + f.puts some_struc(cs,len,2,some_str(@cs_new,@cs_defd,cs),some_str(@cs_local,@cs_used,cs)) + else + f.puts some_struc(cs,len,3,some_str(@cs_new,@cs_defd,cs),some_str(@cs_local,@cs_used,cs)) + end + else + f.puts some_struc(cs,len,4,some_str(@cs_local,@cs_used,cs)) + end + end + if @compact then + # nothing + else + "</dependencies>\n" unless @compact end - else - flushentities($stdout,entities) end + rescue + end + end + + private + + def some_struc(cs,len,type=1,defstr='',usestr='') + if @compact then + "#{cs.ljust(len)} #{@@types[type][1]} #{defstr} #{usestr}" + else + "<macro name='#{cs}' type='#{type}'>\n" + + if defstr.empty? then " <defined/>\n" else " <defined>\n#{defstr} <\defined>\n" end + + if usestr.empty? then " <used/>\n" else " <used>#{usestr}\n <\used>\n" end + + "</macro>\n" end + end + def some_str(files, lines, cs) + return '' unless files[cs] + if @compact then + str = '[ ' + files[cs].each do |c| + str += c + str += " (#{lines[cs][c].join(' ')}) " if lines[cs][c] + str += ' ' + end + str += ']' + str.gsub(/ +/, ' ') + else + str = '' + files[cs].each do |c| + if lines[cs][c] then + str += " <file name='#{c}'>\n" + str += " " + lines[cs][c].each do |l| + # str += " <line n='#{l}'/>\n" + str += "<line n='#{l}'/>" + end + str += "\n" + str += " </file>\n" + else + str += " <file name='#{c}'/>\n" + end + end + str + end + end + + def pushdef(filename,n,cs) + unless @cs_new.key?(cs) then + @cs_new[cs] = Array.new + @cs_defd[cs] = Hash.new unless @cs_defd.key?(cs) + end + @cs_defd[cs][filename] = Array.new unless @cs_defd[cs][filename] + @cs_new[cs].push(filename) unless @cs_new[cs].include?(filename) + @cs_defd[cs][filename] << n + end + + def pushuse(filename,n,cs) + unless @@cs_global.include?(cs.to_s) then + unless @cs_local[cs] then + @cs_local[cs] = Array.new + @cs_used[cs] = Hash.new unless @cs_used.key?(cs) + end + @cs_used[cs][filename] = Array.new unless @cs_used[cs][filename] + @cs_local[cs].push(filename) unless @cs_local[cs].include?(filename) + @cs_used[cs][filename] << n + end end end +class Commands -logger = Logger.new(banner.shift) -commandline = CommandLine.new + include CommandBase -commandline.registeraction('touchcontextfile', 'update context version') -commandline.registeraction('contextversion', 'report context version') + def dependencies -commandline.registeraction('jeditinterface', 'generate jedit syntax files [--pipe]') -commandline.registeraction('bbeditinterface', 'generate bbedit syntax files [--pipe]') -commandline.registeraction('sciteinterface', 'generate scite syntax files [--pipe]') -commandline.registeraction('rawinterface', 'generate raw syntax files [--pipe]') + filename = if @commandline.arguments.empty? then 'context.tex' else @commandline.arguments.first end + compact = @commandline.option('compact') -commandline.registeraction('translateinterface', 'generate interface files (xml) [nl de ..]') -commandline.registeraction('purgefiles', 'remove temporary files [--all --recurse] [basename]') + ['progname=context',''].each do |progname| + unless FileTest.file?(filename) then + name = `kpsewhich #{progname} #{filename}`.chomp + if FileTest.file?(name) then + filename = name + break + end + end + end -commandline.registeraction('documentation', 'generate documentation [--type=] [filename]') + if FileTest.file?(filename) && deps = TexDeps.new(logger) then + deps.load + deps.analyze + deps.feedback(compact) + else + report("unknown file #{filename}") + end -commandline.registeraction('filterpages') # no help, hidden temporary feature -commandline.registeraction('purgeallfiles') # no help, compatibility feature + end -commandline.registeraction('patternfiles', 'generate pattern files [--all --xml --utf8] [languagecode]') +end + +class Commands + + @@re_utf_bom = /^\357\273\277/o # just utf-8 + + def disarmutfbom + + if @commandline.arguments.empty? then + report("provide filename") + else + @commandline.arguments.each do |filename| + report("checking '#{filename}'") + if FileTest.file?(filename) then + begin + data = IO.read(filename) + if data.sub!(@@re_utf_bom,'') then + if @commandline.option('force') then + if f = File.open(filename,'wb') then + f << data + f.close + report("bom found and removed") + else + report("bom found and removed, but saving file fails") + end + else + report("bom found, use '--force' to remove it") + end + else + report("no bom found") + end + rescue + report("bom found, but removing it fails") + end + else + report("provide valid filename") + end + end + end + end + +end + +class Commands + + include CommandBase + + def updatecontext + + def fetchfile(site, name, target=nil) + begin + http = Net::HTTP.new(site) + resp, data = http.get(name.gsub(/^\/*/, '/')) + rescue + return false + else + begin + if data then + name = File.basename(name) + File.open(target || name, 'wb') do |f| + f << data + end + else + return false + end + rescue + return false + else + return true + end + end + end + + def locatedlocaltree + tree = `kpsewhich --expand-path $TEXMFLOCAL`.chomp rescue nil + unless tree && FileTest.directory?(tree) then + tree = `kpsewhich --expand-path $TEXMF`.chomp rescue nil + end + return tree + end -commandline.registeraction('dpxmapfiles', 'convert pdftex mapfiles to dvipdfmx [--force] [texmfroot]') -commandline.registeraction('listentities', 'create doctype entity definition from enco-uc.tex') + def extractarchive(archive) + unless FileTest.file?(archive) then + report("fatal error, '#{archive}' has not been downloaded") + return false + end + unless system("unzip -uo #{archive}") then + report("fatal error, make sure that you have 'unzip' in your path") + return false + end + stubs = "scripts/context/stubs/unix/*" + if System.unix? and not system("chmod +x #{stubs}") then + report("change x-permissions of '#{stubs}' manually") + end + return true + end + + def remakeformats + return system("texmfstart texexec --make --all") + end + + if localtree = locatedlocaltree then + report("updating #{localtree}") + begin + Dir.chdir(localtree) + rescue + report("unable to change to #{localtree}") + else + archive = 'cont-tmf.zip' + report("fetching #{archive}") + unless fetchfile("www.pragma-ade.com","/context/latest/#{archive}") then + report("unable to fetch #{archive}") + return + end + report("extracting #{archive}") + unless extractarchive(archive) then + report("unable to extract #{archive}") + return + end + report("remaking formats") + unless remakeformats then + report("unable to remak formats") + end + end + else + report("unable to locate local tree") + end + + end + +end + +logger = Logger.new(banner.shift) +commandline = CommandLine.new + +commandline.registeraction('touchcontextfile' , 'update context version') +commandline.registeraction('contextversion' , 'report context version') +commandline.registeraction('jeditinterface' , 'generate jedit syntax files [--pipe]') +commandline.registeraction('bbeditinterface' , 'generate bbedit syntax files [--pipe]') +commandline.registeraction('sciteinterface' , 'generate scite syntax files [--pipe]') +commandline.registeraction('rawinterface' , 'generate raw syntax files [--pipe]') +commandline.registeraction('translateinterface', 'generate interface files (xml) [nl de ..]') +commandline.registeraction('purgefiles' , 'remove temporary files [--all --recurse] [basename]') +commandline.registeraction('documentation' , 'generate documentation [--type=] [filename]') +commandline.registeraction('filterpages' ) # no help, hidden temporary feature +commandline.registeraction('patternfiles' , 'generate pattern files [--all --xml --utf8] [languagecode]') +commandline.registeraction('dpxmapfiles' , 'convert pdftex mapfiles to dvipdfmx [--force] [texmfroot]') +commandline.registeraction('listentities' , 'create doctype entity definition from enco-uc.tex') +commandline.registeraction('brandfiles' , 'add context copyright notice [--force]') +commandline.registeraction('platformize' , 'replace line-endings [--recurse --force] [pattern]') +commandline.registeraction('dependencies' , 'analyze depedencies witin context [--compact] [rootfile]') +commandline.registeraction('updatecontext' , 'download latest version and remake formats') +commandline.registeraction('disarmutfbom' , 'remove utf bom [--force]') commandline.registervalue('type','') @@ -1394,6 +2454,7 @@ commandline.registerflag('all') commandline.registerflag('xml') commandline.registerflag('log') commandline.registerflag('utf8') +commandline.registerflag('doctype') # general |