From f8482bca2d7d031de38b8c751aadf5e2523f1a52 Mon Sep 17 00:00:00 2001 From: Hans Hagen Date: Mon, 15 Aug 2005 00:00:00 +0200 Subject: stable 2005.08.15 --- scripts/context/perl/texutil.pl | 4 +- scripts/context/ruby/base/file.rb | 10 + scripts/context/ruby/base/kpsefast.rb | 776 ++++++++++++++++++++++++++++++++++ scripts/context/ruby/base/tex.rb | 4 +- scripts/context/ruby/base/texutil.rb | 113 ++++- scripts/context/ruby/textools.rb | 131 +++--- scripts/context/ruby/tmftools.rb | 131 ++++++ 7 files changed, 1083 insertions(+), 86 deletions(-) create mode 100644 scripts/context/ruby/base/kpsefast.rb create mode 100644 scripts/context/ruby/tmftools.rb (limited to 'scripts') diff --git a/scripts/context/perl/texutil.pl b/scripts/context/perl/texutil.pl index d5e6ef9ea..0a0d29753 100644 --- a/scripts/context/perl/texutil.pl +++ b/scripts/context/perl/texutil.pl @@ -1486,7 +1486,7 @@ if (($SavedHow ne $PageHow) && ($PageHow ne "")) { print TUO "\\registerfrom$SavedLine" } elsif ($RegisterState eq $RegStat{"t"}) { FlushSavedLine ; - print TUO "\\registerto$SavedLine" } + print TUO "\\registerto$SavedLine" ; $SavedHow = '' ; } else { if ($CollapseEntries) { if ($SavedEntry ne $NextEntry) @@ -1495,7 +1495,7 @@ if (($SavedHow ne $PageHow) && ($PageHow ne "")) { { $SavedTo = $SavedLine } $SavedEntry = $NextEntry } else - { print TUO "\\registerpage$SavedLine" } + { print TUO "\\registerpage$SavedLine" ; $SavedHow = '' ; } } ++$NOfSanePages ; $LastPage = $Page ; diff --git a/scripts/context/ruby/base/file.rb b/scripts/context/ruby/base/file.rb index f6189043c..16a1be09b 100644 --- a/scripts/context/ruby/base/file.rb +++ b/scripts/context/ruby/base/file.rb @@ -1,3 +1,13 @@ +# module : base/file +# copyright : PRAGMA Advanced Document Engineering +# version : 2002-2005 +# author : Hans Hagen +# +# project : ConTeXt / eXaMpLe +# concept : Hans Hagen +# info : j.hagen@xs4all.nl +# www : www.pragma-ade.com + require 'ftools' class File diff --git a/scripts/context/ruby/base/kpsefast.rb b/scripts/context/ruby/base/kpsefast.rb new file mode 100644 index 000000000..a519a6be6 --- /dev/null +++ b/scripts/context/ruby/base/kpsefast.rb @@ -0,0 +1,776 @@ +# module : base/kpsefast +# copyright : PRAGMA Advanced Document Engineering +# version : 2005 +# author : Hans Hagen +# +# project : ConTeXt / eXaMpLe +# concept : Hans Hagen +# info : j.hagen@xs4all.nl +# www : www.pragma-ade.com + +# todo: multiple cnf files + +class File + + def File.locate_file(path,name) + begin + files = Dir.entries(path) + if files.include?(name) then + fullname = File.join(path,name) + return fullname if FileTest.file?(fullname) + end + files.each do |p| + fullname = File.join(path,p) + if p != '.' and p != '..' and FileTest.directory?(fullname) and result = locate_file(fullname,name) then + return result + end + end + rescue + # bad path + end + return nil + end + + def File.glob_file(pattern) + return Dir.glob(pattern).first + end + +end + +class KPSEFAST + + # formats are an incredible inconsistent mess + + @@suffixes = Hash.new + @@formats = Hash.new + @@suffixmap = Hash.new + + @@suffixes['gf'] = ['.gf'] # todo + @@suffixes['pk'] = ['.pk'] # todo + @@suffixes['tfm'] = ['.tfm'] + @@suffixes['afm'] = ['.afm'] + @@suffixes['base'] = ['.base'] + @@suffixes['bib'] = ['.bib'] + @@suffixes['bst'] = ['.bst'] + @@suffixes['cnf'] = ['.cnf'] + @@suffixes['ls-R'] = ['ls-R', 'ls-r'] + @@suffixes['fmt'] = ['.fmt', '.efmt', '.efm', '.ofmt', '.ofm', '.oft', '.eofmt', '.eoft', '.eof', '.pfmt', '.pfm', '.epfmt', '.epf', '.xpfmt', '.xpf', '.afmt', '.afm'] + @@suffixes['map'] = ['.map'] + @@suffixes['mem'] = ['.mem'] + @@suffixes['mf'] = ['.mf'] + @@suffixes['mfpool'] = ['.pool'] + @@suffixes['mft'] = ['.mft'] + @@suffixes['mp'] = ['.mp'] + @@suffixes['mppool'] = ['.pool'] + @@suffixes['ocp'] = ['.ocp'] + @@suffixes['ofm'] = ['.ofm', '.tfm'] + @@suffixes['opl'] = ['.opl'] + @@suffixes['otp'] = ['.otp'] + @@suffixes['ovf'] = ['.ovf'] + @@suffixes['ovp'] = ['.ovp'] + @@suffixes['graphic/figure'] = ['.eps', '.epsi'] + @@suffixes['tex'] = ['.tex'] + @@suffixes['texpool'] = ['.pool'] + @@suffixes['PostScript header'] = ['.pro'] + @@suffixes['type1 fonts'] = ['.pfa', '.pfb'] + @@suffixes['vf'] = ['.vf'] + @@suffixes['ist'] = ['.ist'] + @@suffixes['truetype fonts'] = ['.ttf', '.ttc'] + @@suffixes['web'] = ['.web', '.ch'] + @@suffixes['cweb'] = ['.w', '.web', '.ch'] + @@suffixes['enc files'] = ['.enc'] + @@suffixes['cmap files'] = ['.cmap'] + @@suffixes['subfont definition files'] = ['.sfd'] + @@suffixes['lig files'] = ['.lig'] + @@suffixes['bitmap font'] = [] + @@suffixes['MetaPost support'] = [] + @@suffixes['TeX system documentation'] = [] + @@suffixes['TeX system sources'] = [] + @@suffixes['Troff fonts'] = [] + @@suffixes['dvips config'] = [] + @@suffixes['type42 fonts'] = [] + @@suffixes['web2c files'] = [] + @@suffixes['other text files'] = [] + @@suffixes['other binary files'] = [] + @@suffixes['misc fonts'] = [] + @@suffixes['opentype fonts'] = [] + @@suffixes['pdftex config'] = [] + @@suffixes['texmfscripts'] = [] + + # replacements + + @@suffixes['fmt'] = ['.fmt'] + @@suffixes['type1 fonts'] = ['.pfa', '.pfb', '.pfm'] + @@suffixes['tex'] = ['.tex', '.xml'] + @@suffixes['texmfscripts'] = ['rb','lua','py','pl'] + + @@suffixes.keys.each do |k| @@suffixes[k].each do |s| @@suffixmap[s] = k end end + + # TTF2TFMINPUTS + # MISCFONTS + # TEXCONFIG + # DVIPDFMINPUTS + # OTFFONTS + + @@formats['gf'] = '' + @@formats['pk'] = '' + @@formats['tfm'] = 'TFMFONTS' + @@formats['afm'] = 'AFMFONTS' + @@formats['base'] = 'MFBASES' + @@formats['bib'] = '' + @@formats['bst'] = '' + @@formats['cnf'] = '' + @@formats['ls-R'] = '' + @@formats['fmt'] = '' + @@formats['map'] = 'TEXFONTMAPS' + @@formats['mem'] = 'MPMEMS' + @@formats['mf'] = 'MFINPUTS' + @@formats['mfpool'] = 'MFPOOL' + @@formats['mft'] = '' + @@formats['mp'] = 'MPINPUTS' + @@formats['mppool'] = 'MPPOOL' + @@formats['ocp'] = 'OCPINPUTS' + @@formats['ofm'] = 'OFMFONTS' + @@formats['opl'] = 'OPLFONTS' + @@formats['otp'] = 'OTPINPUTS' + @@formats['ovf'] = 'OVFFONTS' + @@formats['ovp'] = 'OVPFONTS' + @@formats['graphic/figure'] = '' + @@formats['tex'] = 'TEXINPUTS' + @@formats['texpool'] = 'TEXPOOL' + @@formats['PostScript header'] = 'TEXPSHEADERS' + @@formats['type1 fonts'] = 'T1FONTS' + @@formats['vf'] = 'VFFONTS' + @@formats['ist'] = '' + @@formats['truetype fonts'] = 'TTFONTS' + @@formats['web'] = '' + @@formats['cweb'] = '' + @@formats['enc files'] = 'ENCFONTS' + @@formats['cmap files'] = 'CMAPFONTS' + @@formats['subfont definition files'] = 'SFDFONTS' + @@formats['lig files'] = 'LIGFONTS' + @@formats['bitmap font'] = '' + @@formats['MetaPost support'] = '' + @@formats['TeX system documentation'] = '' + @@formats['TeX system sources'] = '' + @@formats['Troff fonts'] = '' + @@formats['dvips config'] = '' + @@formats['type42 fonts'] = 'T42FONTS' + @@formats['web2c files'] = 'WEB2C' + @@formats['other text files'] = '' + @@formats['other binary files'] = '' + @@formats['misc fonts'] = '' + @@formats['opentype fonts'] = 'OPENTYPEFONTS' + @@formats['pdftex config'] = 'PDFTEXCONFIG' + @@formats['texmfscripts'] = 'TEXMFSCRIPTS' + + attr_accessor :progname, :engine, :format, :rootpath, :treepath, + :verbose, :remember, :scandisk, :diskcache, :renewcache + + @@cacheversion = '1' + + def initialize + @rootpath = '' + @treepath = '' + @progname = 'kpsewhich' + @engine = 'pdfetex' + @variables = Hash.new + @expansions = Hash.new + @files = Hash.new + @found = Hash.new + @kpsevars = Hash.new + @lsrfiles = Array.new + @verbose = true + @remember = true + @scandisk = true + @diskcache = true + @renewcache = false + @isolate = false + + @diskcache = false + @cachepath = nil + @cachefile = 'tmftools.log' + end + + def load_cnf + unless @treepath.empty? then + unless @rootpath.empty? then + @treepath = @treepath.split(',').collect do |p| File.join(@rootpath,p) end.join(',') + end + ENV['TEXMF'] = @treepath + ENV['TEXMFCNF'] = File.join(@treepath.split(',').first,'texmf/web2c') + end + unless @rootpath.empty? then + ENV['TEXMFCNF'] = File.join(@rootpath,'texmf/web2c') + ENV['SELFAUTOPARENT'] = @rootpath + @isolate = true + end + filenames = [File.join(ENV['TEXMFCNF'] || '.','texmf.cnf')] + # /texmf/web2c/texmf.cnf + @rootpath = filenames.first + 3.times do + @rootpath = File.dirname(@rootpath) + end + filenames.collect! do |f| + f.gsub("\\", '/') + end + filenames.each do |fname| + if FileTest.file?(fname) and f = File.open(fname) then + while line = f.gets do + loop do + # concatenate lines ending with \ + break unless line.sub!(/\\\s*$/o) do + f.gets || '' + end + end + case line + when /^[\%\#]/o then + # comment + when /^\s*(.*?)\s*\=\s*(.*?)\s*$/o then + key, value = $1, $2 + unless @variables.key?(key) then + value.sub!(/\%.*$/,'') + value.sub!(/\~/, "$HOME") + @variables[key] = value + end + @kpsevars[key] = true + end + end + f.close + end + end + end + + def load_lsr + @lsrfiles = [] + simplified_list(expansion('TEXMF')).each do |p| + ['ls-R','ls-r'].each do |f| + filename = File.join(p,f) + if FileTest.file?(filename) then + @lsrfiles << [filename,File.size(filename)] + break + end + end + end + @files = Hash.new + if @diskcache then + ['HOME','TEMP','TMP','TMPDIR'].each do |key| + if ENV[key] then + if FileTest.directory?(ENV[key]) then + @cachepath = ENV[key] + @cachefile = [@rootpath.gsub(/[^A-Z0-9]/io, '-').gsub(/\-+/,'-'),File.basename(@cachefile)].join('-') + break + end + end + end + if @cachepath and not @renewcache and FileTest.file?(File.join(@cachepath,@cachefile)) then + begin + if f = File.open(File.join(@cachepath,@cachefile)) then + cacheversion = Marshal.load(f) + if cacheversion == @@cacheversion then + lsrfiles = Marshal.load(f) + if lsrfiles == @lsrfiles then + @files = Marshal.load(f) + end + end + f.close + end + rescue + @files = Hash.new + end + end + end + return if @files.size > 0 + @lsrfiles.each do |filedata| + filename, filesize = filedata + filepath = File.dirname(filename) + begin + path = '.' + data = IO.readlines(filename) + if data[0].chomp =~ /% ls\-R \-\- filename database for kpathsea\; do not change this line\./io then + data.each do |line| + case line + when /^[a-zA-Z0-9]/o then + line.chomp! + if @files[line] then + @files[line] << path + else + @files[line] = [path] + end + when /^\.\/(.*?)\:$/o then + path = File.join(filepath,$1) + end + end + end + rescue + # sorry + end + end + if @diskcache and @cachepath and f = File.open(File.join(@cachepath,@cachefile),'wb') then + f << Marshal.dump(@@cacheversion) + f << Marshal.dump(@lsrfiles) + f << Marshal.dump(@files) + f.close + end + end + + def expand_variables + @expansions = Hash.new + if @isolate then + @variables['TEXMFCNF'] = ENV['TEXMFCNF'].dup + @variables['SELFAUTOPARENT'] = ENV['SELFAUTOPARENT'].dup + else + ENV.keys.each do |e| + if e =~ /^([a-zA-Z]+)\_(.*)\s*$/o then + @expansions["#{$1}.#{$2}"] = ENV[e].dup + else + @expansions[e] = ENV[e].dup + end + end + end + @variables.keys.each do |k| + @expansions[k] = @variables[k].dup unless @expansions[k] + end + loop do + busy = false + @expansions.keys.each do |k| + @expansions[k].gsub!(/\$([a-zA-Z0-9\_\-]*)/o) do + busy = true + @expansions[$1] || '' + end + @expansions[k].gsub!(/\$\{([a-zA-Z0-9\_\-]*)\}/o) do + busy = true + @expansions[$1] || '' + end + end + break unless busy + end + @expansions.keys.each do |k| + @expansions[k] = @expansions[k].gsub("\\", '/') + end + end + + def variable(name='') + (name and not name.empty? and @variables[name.sub('$','')]) or '' + end + + def expansion(name='') + (name and not name.empty? and @expansions[name.sub('$','')]) or '' + end + + def variable?(name='') + name and not name.empty? and @variables.key?(name.sub('$','')) + end + + def expansion?(name='') + name and not name.empty? and @expansions.key?(name.sub('$','')) + end + + def simplified_list(str) + lst = str.gsub(/^\{/o,'').gsub(/\}$/o,'').split(",") + lst.collect do |l| + l.sub(/^[\!]*/,'').sub(/[\/\\]*$/o,'') + end + end + + def original_variable(variable) + if variable?("#{@progname}.#{variable}") then + variable("#{@progname}.#{variable}") + elsif variable?(variable) then + variable(variable) + else + '' + end + end + + def expanded_variable(variable) + if expansion?("#{variable}.#{@progname}") then + expansion("#{variable}.#{@progname}") + elsif expansion?(variable) then + expansion(variable) + else + '' + end + end + + def original_path(filename='') + _expanded_path_(original_variable(var_of_format_or_suffix(filename)).split(";")) + end + + def expanded_path(filename='') + _expanded_path_(expanded_variable(var_of_format_or_suffix(filename)).split(";")) + end + + def _expanded_path_(pathlist) + i, n = 0, 0 + pathlist.collect! do |mainpath| + mainpath.gsub(/([\{\}])/o) do + if $1 == "{" then + i += 1 ; n = i if i > n ; "<#{i}>" + else + i -= 1 ; "" + end + end + end + n.times do |i| + loop do + more = false + newlist = [] + pathlist.each do |path| + unless path.sub!(/^(.*?)<(#{n-i})>(.*?)<\/\2>(.*?)$/) do + pre, mid, post = $1, $3, $4 + mid.gsub!(/\,$/,',.') + mid.split(',').each do |m| + more = true + if m == '.' then + newlist << "#{pre}#{post}" + else + newlist << "#{pre}#{m}#{post}" + end + end + end then + newlist << path + end + end + if more then + pathlist = [newlist].flatten # copy -) + else + break + end + end + end + pathlist = pathlist.uniq.collect do |path| + p = path.gsub(/^\/+/o) do '' end + # p.gsub!(/(.)\/\/(.)/o) do "#{$1}/#{$2}" end + # p.gsub!(/\/\/+$/o) do '//' end + p.gsub!(/\/\/+/o) do '//' end + p + end + pathlist + end + + # todo: ignore case + + def var_of_format(str) + @@formats[str] || '' + end + + def var_of_suffix(str) # includes . + if @@suffixmap.key?(str) then @@formats[@@suffixmap[str]] else '' end + end + + def var_of_format_or_suffix(str) + if @@formats.key?(@format) then + @@formats[@format] + elsif @@suffixmap.key?(File.extname(str)) then # extname includes . + @@formats[@@suffixmap[File.extname(str)]] # extname includes . + else + '' + end + end + +end + +class KPSEFAST + + # test things + + def list_variables(kpseonly=true) + @variables.keys.sort.each do |k| + if kpseonly then + puts("#{k} = #{@variables[k]}") if @kpsevars[k] + else + puts("#{if @kpsevars[k] then 'K' else 'E' end} #{k} = #{@variables[k]}") + end + end + end + + def list_expansions(kpseonly=true) + @expansions.keys.sort.each do |k| + if kpseonly then + puts("#{k} = #{@expansions[k]}") if @kpsevars[k] + else + puts("#{if @kpsevars[k] then 'K' else 'E' end} #{k} = #{@expansions[k]}") + end + end + end + + def list_lsr + puts("files = #{@files.size}") + end + + def set_test_patterns + @variables["KPSE_TEST_PATTERN_A"] = "foo/{1,2}/bar//" + @variables["KPSE_TEST_PATTERN_B"] = "!!x{A,B{1,2}}y" + @variables["KPSE_TEST_PATTERN_C"] = "x{A,B//{1,2}}y" + @variables["KPSE_TEST_PATTERN_D"] = "x{A,B//{1,2,}}//y" + end + + def show_test_patterns + ['A','B','D'].each do |i| + puts "" + puts @variables ["KPSE_TEST_PATTERN_#{i}"] + puts "" + puts expand_path("KPSE_TEST_PATTERN_#{i}").split(File::PATH_SEPARATOR) + puts "" + end + end + +end + +class KPSEFAST + + # kpse stuff + + def expand_braces(str) # output variable and brace expansion of STRING. + _expanded_path_(original_variable(str).split(";")).join(File::PATH_SEPARATOR) + end + + def expand_path(str) # output complete path expansion of STRING. + _expanded_path_(expanded_variable(str).split(";")).join(File::PATH_SEPARATOR) + end + + def expand_var(str) # output variable expansion of STRING. + expanded_variable(str) + end + + def show_path(str) # output search path for file type NAME + expanded_path(var_of_format(str)).join(File::PATH_SEPARATOR) + end + + def var_value(str) # output the value of variable $STRING. + original_variable(str) + end + +end + +class KPSEFAST + + def find_file(filename) + find_files(filename,true) + end + + def find_files(filename,first=false) + if @remember then + stamp = "#{filename}--#{@format}--#{@engine}--#{@progname}" + return @found[stamp] if @found.key?(stamp) + end + pathlist = expanded_path(filename) + result = [] + filelist = if @files.key?(filename) then @files[filename].uniq else nil end + done = false + pathlist.each do |path| + doscan = if path =~ /^\!\!/o then false else true end + recurse = if path =~ /\/\/$/o then true else false end + pathname = path.dup + pathname.gsub!(/^\!+/o, '') + done = false + if not done and filelist then + # checking for exact match + if filelist.include?(pathname) then + result << pathname + done = true + end + if not done and recurse then + # checking for fuzzy // + pathname.gsub!(/\/+$/o, '/.*') + # pathname.gsub!(/\/\//o,'/[\/]*/') + pathname.gsub!(/\/\//o,'/.*?/') + re = /^#{pathname}/ + filelist.each do |f| + if re =~ f then + result << f # duplicates will be filtered later + done = true + end + break if done + end + end + end + if not done and doscan then + # checking for path itself + pname = pathname.sub(/\.\*$/,'') + if not pname =~ /\*/o and FileTest.file?(File.join(pname,filename)) then + result << pname + done = true + end + end + break if done and first + end + if not done and @scandisk then + pathlist.each do |path| + pathname = path.dup + unless pathname.gsub!(/^\!+/o, '') then # !! prevents scan + recurse = pathname.gsub!(/\/+$/o, '') + complex = pathname.gsub!(/\/\//o,'/*/') + if recurse then + if complex then + if ok = File.glob_file("#{pathname}/**/#{filename}") then + result << File.dirname(ok) + done = true + end + elsif ok = File.locate_file(pathname,filename) then + result << File.dirname(ok) + done = true + end + elsif complex then + if ok = File.glob_file("#{pathname}/#{filename}") then + result << File.dirname(ok) + done = true + end + elsif FileTest.file?(File.join(pathname,filename)) then + result << pathname + done = true + end + break if done and first + end + end + end + result = result.uniq.collect do |pathname| + File.join(pathname,filename) + end + @found[stamp] = result if @remember + return result # redundant + end + +end + +class KPSEFAST + + class FileData + attr_accessor :tag, :name, :size, :date + def initialize(tag=0,name=nil,size=nil,date=nil) + @tag, @name, @size, @date = tag, name, size, date + end + def FileData.sizes(a) + a.collect do |aa| + aa.size + end + end + def report + case @tag + when 1 + "deleted | #{@size.to_s.rjust(8)} | #{@date.strftime('%m/%d/%Y %I:%M')} | #{@name}" + when 2 + "present | #{@size.to_s.rjust(8)} | #{@date.strftime('%m/%d/%Y %I:%M')} | #{@name}" + when 3 + "obsolete | #{' '*8} | #{' '*16} | #{@name}" + end + end + end + + def analyze_files(filter='',strict=false,sort='',delete=false) + puts("command = #{ARGV.join(' ')}") + puts("files = #{@files.size}") + puts("filter = #{filter}") + puts('') + if filter.gsub!(/^not:/,'') then + def the_same(filter,filename) + not filter or filter.empty? or /#{filter}/ !~ filename + end + else + def the_same(filter,filename) + not filter or filter.empty? or /#{filter}/ =~ filename + end + end + @files.keys.each do |name| + if @files[name].size > 1 then + data = Array.new + @files[name].each do |path| + filename = File.join(path,name) + # if not filter or filter.empty? or /#{filter}/ =~ filename then + if the_same(filter,filename) then + if FileTest.file?(filename) then + if delete then + data << FileData.new(1,filename,File.size(filename),File.mtime(filename)) + begin + File.delete(filename) if delete + rescue + end + else + data << FileData.new(2,filename,File.size(filename),File.mtime(filename)) + end + else + data << FileData.new(3,filename) + end + end + end + if data.length > 1 then + if strict then + # if data.collect do |d| d.size end.uniq! then + # data.sort! do |a,b| b.size <=> a.size end + # data.each do |d| puts d.report end + # puts '' + # end + data.sort! do |a,b| b.size <=> a.size end + bunch = Array.new + done = false + data.each do |d| + if bunch.size == 0 then + bunch << d + elsif bunch[0].size == d.size then + bunch << d + else + if bunch.size > 1 then + bunch.each do |b| + puts b.report + end + done = true + end + bunch = [d] + end + end + puts '' if done + else + case sort + when 'size' then data.sort! do |a,b| a.size <=> b.size end + when 'revsize' then data.sort! do |a,b| b.size <=> a.size end + when 'date' then data.sort! do |a,b| a.date <=> b.date end + when 'revdate' then data.sort! do |a,b| b.date <=> a.date end + end + data.each do |d| puts d.report end + puts '' + end + end + end + end + end + +end + +if false then + + k = KPSEFAST.new # (root) + k.set_test_patterns + k.load_cnf + k.expand_variables + k.load_lsr + + k.show_test_patterns + # puts k.list_variables + # puts k.list_expansions + # k.list_lsr + # puts k.expansion("$TEXMF") + # puts k.expanded_path("TEXINPUTS","context") + + # k.progname, k.engine, k.format = 'context', 'pdfetex', 'tfm' + # k.scandisk = false # == must_exist + # k.expand_variables + + # 10.times do |i| puts k.find_file('texnansi-lmr10.tfm') end + + # puts "expand braces $TEXMF" + # puts k.expand_braces("$TEXMF") + # puts "expand path $TEXMF" + # puts k.expand_path("$TEXMF") + # puts "expand var $TEXMF" + # puts k.expand_var("$TEXMF") + # puts "expand path $TEXMF" + # puts k.show_path('tfm') + # puts "expand value $TEXINPUTS" + # puts k.var_value("$TEXINPUTS") + # puts "expand value $TEXINPUTS.context" + # puts k.var_value("$TEXINPUTS.context") + + exit + +end diff --git a/scripts/context/ruby/base/tex.rb b/scripts/context/ruby/base/tex.rb index e2013b87e..75970bcd8 100644 --- a/scripts/context/ruby/base/tex.rb +++ b/scripts/context/ruby/base/tex.rb @@ -118,7 +118,7 @@ class TEX @@booleanvars = [ 'batchmode', 'nonstopmode', 'fast', 'fastdisabled', 'silentmode', 'final', - 'paranoid', 'notparanoid', 'nobanner', 'once', 'allpatterrns', + 'paranoid', 'notparanoid', 'nobanner', 'once', 'allpatterns', 'nompmode', 'nomprun', 'automprun', 'nomapfiles', 'local', 'arrange', 'noarrange', @@ -873,7 +873,7 @@ class TEX if getvariable('fast') && ! getvariable('fastdisabled') then opt << "\\fastmode\n" end - if getvariable('silent') then + if getvariable('silentmode') then opt << "\\silentmode\n" end if (str = getvariable('separation')) && ! str.empty? then diff --git a/scripts/context/ruby/base/texutil.rb b/scripts/context/ruby/base/texutil.rb index 083e11bdb..47c613474 100644 --- a/scripts/context/ruby/base/texutil.rb +++ b/scripts/context/ruby/base/texutil.rb @@ -127,12 +127,13 @@ class TeXUtil class Sorter def initialize(max=12) - @rep, @map, @exp = Hash.new, Hash.new, Hash.new + @rep, @map, @exp, @div = Hash.new, Hash.new, Hash.new, Hash.new @max = max @rexa, @rexb = nil, nil end def replacer(from,to='') # and expand + @max = [@max,to.length+1].max if to @rep[from.escaped] = to || '' end @@ -140,6 +141,7 @@ class TeXUtil # sorter.reducer('ij', 'y') def reducer(from,to='') + @max = [@max,to.length+1].max if to @map[from] = to || '' end @@ -147,9 +149,17 @@ class TeXUtil # sorter.expander('ijligature', 'y') def expander(from,to=nil) + from, to = converted(from), converted(to) + @max = [@max,to.length+1].max if to @exp[from] = to || from || '' end + def division(from,to=nil) + from, to = converted(from), converted(to) + @max = [@max,to.length+1].max if to + @div[from] = to || from || '' + end + # shortcut("\\ab\\cd\\e\\f", 'iacute') # shortcut("\\\'\\i", 'iacute') # shortcut("\\\'i", 'iacute') @@ -172,9 +182,14 @@ class TeXUtil end def remap(str) - str.gsub(@rexa) do + s = str.dup + s.gsub!(/(\d+)/o) do + $1.rjust(10,'a') # rest is b .. k + end + s.gsub!(@rexa) do @rep[$1.escaped] - end.gsub(@rexb) do + end + s.gsub!(@rexb) do token = $1.sub(/\\/o, '') if @exp.key?(token) then @exp[token].ljust(@max,' ') @@ -184,15 +199,20 @@ class TeXUtil '' end end + s end - def preset(shortcuts=[],expansions=[],reductions=[]) - 'a'.upto('z') do |c| - expander(c) - end + def preset(shortcuts=[],expansions=[],reductions=[],divisions=[]) + # maybe we should move this to sort-def.tex + 'a'.upto('z') do |c| expander(c) ; division(c) end + expander('1','b') ; expander('2','c') ; expander('3','e') ; expander('4','f') + expander('5','g') ; expander('6','h') ; expander('7','i') ; expander('8','i') + expander('9','j') ; expander('0','a') ; expander('-','-') ; + # end potential move 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 + divisions.each do |d| division(d[0],d[1]) end end def simplify(str) @@ -216,6 +236,33 @@ class TeXUtil return s end + def getdivision(str) + @div[str] || str + end + + def division?(str) + @div.key?(str) + end + + private + + def converted(str) + if str then + str.gsub(/([\+\-]*\d+)/o) do + n = $1.to_i + if n > 0 then + 'z'*n + elsif n < 0 then + '-'*(-n) # '-' precedes 'a' + else + '' + end + end + else + nil + end + end + end class Plugin @@ -328,6 +375,7 @@ class TeXUtil class Synonym + @@debug = false @@debug = true def initialize(t, c, k, d) @@ -386,7 +434,7 @@ class TeXUtil def MySynonyms::processor(logger) sorter = Sorter.new - sorter.preset(eval("MyKeys").shortcuts,eval("MyKeys").expansions,eval("MyKeys").reductions) + sorter.preset(eval("MyKeys").shortcuts,eval("MyKeys").expansions,eval("MyKeys").reductions,eval("MyKeys").divisions) sorter.prepare @@synonyms.keys.each do |s| @@synonyms[s].each_index do |i| @@ -406,6 +454,7 @@ class TeXUtil class Register + @@debug = false @@debug = true @@howto = /^(.*?)\:\:(.*)$/o @@ -474,30 +523,43 @@ class TeXUtil @@savedhowto, @@savedfrom, @@savedto, @@savedentry = '', '', '', '' end - def Register.flush(list,handle) - # + def Register.flush(list,handle,sorter) + # a bit messy, quite old mechanism, maybe some day ... # 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" + handle << "% [#{entry.sortkey.gsub(/#{@@split}/o,'] [')}]\n" end end list.each do |entry| - testalpha = entry.sortkey[0,1].downcase + if entry.sortkey =~ /^(\S+)/o then + if sorter.division?($1) then + testalpha = sorter.getdivision($1) + else + testalpha = entry.sortkey[0,1].downcase + end + else + testalpha = entry.sortkey[0,1].downcase + end 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 + if alpha =~ /^[a-zA-Z]$/o then + character = alpha.dup + elsif alpha.length > 1 then + # character = "\\getvalue\{#{alpha}\}" + character = "\\#{alpha}" + else + character = "\\#{alpha}" + end handle << "\\registerentry{#{entry.type}}{#{character}}\n" end end @@ -556,6 +618,7 @@ class TeXUtil elsif entry.state == 3 then # to Register.flushsavedline(handle) handle << "\\registerto#{savedline}\n" + @@savedhowto = '' # test elsif @@collapse then if savedentry != nextentry then savedFrom = savedline @@ -564,6 +627,7 @@ class TeXUtil end else handle << "\\registerpage#{savedline}\n" + @@savedhowto = '' # test end @nofpages += 1 lastpage, lastrealpage = entry.page, entry.realpage @@ -576,9 +640,11 @@ class TeXUtil end @@registers = Hash.new + @@sorter = Sorter.new def MyRegisters::reset(logger) @@registers = Hash.new + @@sorter = Sorter.new end def MyRegisters::reader(logger,data) @@ -602,19 +668,18 @@ class TeXUtil if @@registers.size > 0 then @@registers.keys.sort.each do |s| handle << logger.banner("registers: #{s} #{@@registers[s].size}") - Register.flush(@@registers[s],handle) + Register.flush(@@registers[s],handle,@@sorter) # 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 + @@sorter.preset(eval("MyKeys").shortcuts,eval("MyKeys").expansions,eval("MyKeys").reductions,eval("MyKeys").divisions) + @@sorter.prepare @@registers.keys.each do |s| @@registers[s].each_index do |i| - @@registers[s][i].build(sorter) + @@registers[s][i].build(@@sorter) end @@registers[s] = @@registers[s].sort end @@ -668,6 +733,7 @@ class TeXUtil @@shortcuts = Array.new @@expansions = Array.new @@reductions = Array.new + @@divisions = Array.new def MyKeys::shortcuts @@shortcuts @@ -678,6 +744,9 @@ class TeXUtil def MyKeys::reductions @@reductions end + def MyKeys::divisions + @@divisions + end def MyKeys::reset(logger) @@shortcuts = Array.new @@ -692,6 +761,7 @@ class TeXUtil when 's' then @@shortcuts.push(data) when 'e' then @@expansions.push(data) when 'r' then @@reductions.push(data) + when 'd' then @@divisions.push(data) end end @@ -699,9 +769,10 @@ class TeXUtil end def MyKeys::processor(logger) - logger.report("shortcuts: #{@@shortcuts.size}") # logger.report(@@shortcuts.inspect) + 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) + logger.report("divisions : #{@@divisions.size}") # logger.report(@@divisions.inspect) end end diff --git a/scripts/context/ruby/textools.rb b/scripts/context/ruby/textools.rb index 50b72241a..bf0639328 100644 --- a/scripts/context/ruby/textools.rb +++ b/scripts/context/ruby/textools.rb @@ -727,10 +727,10 @@ class Commands nocheck = @commandline.option('nocheck') merge = @commandline.option('merge') - prune = @commandline.option('prune') + delete = @commandline.option('delete') force = @commandline.option('force') - root = @commandline.argument('first') - path = @commandline.argument('second') + root = @commandline.argument('first').gsub(/\\/,'/') + path = @commandline.argument('second').gsub(/\\/,'/') if FileTest.directory?(root) then report("scanning #{root}") @@ -745,6 +745,12 @@ class Commands report("no files") return end + rootfiles.collect! do |rf| + rf.gsub(/\\/o, '/').sub(/#{root}\//o, '') + end + rootfiles = rootfiles.delete_if do |rf| + FileTest.directory?(File.join(root,rf)) + end if FileTest.directory?(path) then report("scanning #{path}") @@ -759,83 +765,85 @@ class Commands report("no files") return end - - roothash = Hash.new - pathhash = Hash.new - - rootfiles.each do |f| - if File.file?(f) then - fd, fb = File.dirname(f), File.basename(f) - roothash[fb] = if roothash.key?(fb) then nil else fd end - end + pathfiles.collect! do |pf| + pf.gsub(/\\/o, '/').sub(/#{path}\//o, '') end - - pathfiles.each do |f| - if File.file?(f) then - fd, fb = File.dirname(f), File.basename(f) - pathhash[fb] = if pathhash.key?(fb) then nil else fd end - end + pathfiles = pathfiles.delete_if do |pf| + FileTest.directory?(File.join(path,pf)) end - donehash = Hash.new - copied = Array.new + root = File.expand_path(root) + path = File.expand_path(path) + + donepaths = Hash.new + copiedfiles = Hash.new - pathhash.keys.each do |f| - if pathhash[f] and roothash[f] then - p = File.expand_path(File.join(pathhash[f],f)) # destination - r = File.expand_path(File.join(roothash[f],f)) + # update existing files, assume similar paths + + report("") + pathfiles.each do |f| # destination + p = File.join(path,f) + if rootfiles.include?(f) then + r = File.join(root,f) if p != r then - if not FileTest.file?(p) then - if merge then - report("merging '#{r}' to '#{p}'") - begin - File.copy(r,p) if force - copied << p - rescue - report("merging failed") - else - donehash[File.dirname(r)] = File.dirname(p) - end - else - report("not merging '#{r}'") - end - elsif nocheck or File.mtime(p) < File.mtime(r) then + if nocheck or File.mtime(p) < File.mtime(r) then + copiedfiles[File.expand_path(p)] = true report("updating '#{r}' to '#{p}'") begin + begin File.makedirs(File.dirname(p)) if force ; rescue ; end File.copy(r,p) if force - copied << p rescue report("updating failed") - else - donehash[File.dirname(r)] = File.dirname(p) end else report("not updating '#{r}'") - report("old > #{File.mtime(p)}") - report("new > #{File.mtime(r)}") end end end end + # merging non existing files + report("") - donehash.keys.sort.each do |d| - rootfiles = Dir.glob("#{d}/**/*") - pathfiles = Dir.glob("#{donehash[d]}/**/*") - pathfiles.collect! do |file| File.expand_path(file) end - rootfiles.collect! do |file| File.expand_path(file) end - difference = pathfiles - rootfiles - copied - if difference.length > 0 then - length = 0 - difference.each do |file| - if l = File.basename(file).length and l > length then length = l end + rootfiles.each do |f| + donepaths[File.dirname(f)] = true + r = File.join(root,f) + if not pathfiles.include?(f) then + p = File.join(path,f) + if p != r then + if merge then + copiedfiles[File.expand_path(p)] = true + report("merging '#{r}' to '#{p}'") + begin + begin File.makedirs(File.dirname(p)) if force ; rescue ; end + File.copy(r,p) if force + rescue + report("merging failed") + end + else + report("not merging '#{r}'") + end end - report("") - difference.sort.each do |file| - if prune then - report("deleting '#{file.ljust(length)}'") + end + end + + # deleting obsolete files + + report("") + donepaths.keys.sort.each do |d| + pathfiles = Dir.glob("#{path}/#{d}/**/*") + pathfiles.each do |p| + r = File.join(root,d,File.basename(p)) + if FileTest.file?(p) and not FileTest.file?(r) and not copiedfiles.key?(File.expand_path(p)) then + if delete then + report("deleting '#{p}'") + begin + File.delete(p) if force + rescue + report("deleting failed") + end else - report("keeping '#{file.ljust(length)}'") + report("not deleting '#{p}'") end end end @@ -858,7 +866,7 @@ commandline.registeraction('fixafmfiles' , '[pattern] [--recurse]') commandline.registeraction('mactodos' , '[pattern] [--recurse]') commandline.registeraction('fixtexmftrees' , '[texmfroot] [--force]') commandline.registeraction('replacefile' , 'filename [--force]') -commandline.registeraction('updatetree' , 'fromroot toroot [--force --nocheck --merge --prune]') +commandline.registeraction('updatetree' , 'fromroot toroot [--force --nocheck --merge --delete]') commandline.registeraction('downcasefilenames', '[--recurse] [--force]') # not yet documented commandline.registeraction('stripformfeeds' , '[--recurse] [--force]') # not yet documented commandline.registeraction('showfont' , 'filename') @@ -868,7 +876,8 @@ commandline.registeraction('version') commandline.registerflag('recurse') commandline.registerflag('force') -commandline.registerflag('prune') +commandline.registerflag('merge') +commandline.registerflag('delete') commandline.registerflag('nocheck') commandline.expand diff --git a/scripts/context/ruby/tmftools.rb b/scripts/context/ruby/tmftools.rb new file mode 100644 index 000000000..305a52370 --- /dev/null +++ b/scripts/context/ruby/tmftools.rb @@ -0,0 +1,131 @@ +#!/usr/bin/env ruby + +# program : tmftools +# copyright : PRAGMA Advanced Document Engineering +# version : 2005 +# author : Hans Hagen +# +# project : ConTeXt +# concept : Hans Hagen +# info : j.hagen@xs4all.nl +# www : www.pragma-ade.com + +# The script based alternative is not slower than the kpse one. +# Loading is a bit faster when the log file is used. + +# tmftools [some of the kpsewhich switches] + +# tmftools --analyze +# tmftools --analyze > kpsewhat.log +# tmftools --analyze --strict > kpsewhat.log +# tmftools --analyze --delete --force "texmf-local/fonts/.*/somename" + +# the real thing + +banner = ['TMFTools', 'version 1.0.0 (experimental, no help yet)', '2005', 'PRAGMA ADE/POD'] + +unless defined? ownpath + ownpath = $0.sub(/[\\\/][a-z0-9\-]*?\.rb/i,'') + $: << ownpath +end + +require 'base/switch' +require 'base/logger' +require 'base/kpsefast' + +class Commands + + include CommandBase + + def init_kpse + k = KPSEFAST.new + k.rootpath = @commandline.option('rootpath') + k.treepath = @commandline.option('treepath') + k.progname = @commandline.option('progname') + k.engine = @commandline.option('engine') + k.format = @commandline.option('format') + k.diskcache = @commandline.option('diskcache') + k.renewcache = @commandline.option('renewcache') + k.load_cnf + k.expand_variables + k.load_lsr + return k + end + + def main + if option = @commandline.option('expand-braces') and not option.empty? then + puts init_kpse.expand_braces(option) + elsif option = @commandline.option('expand-path') and not option.empty? then + puts init_kpse.expand_path(option) + elsif option = @commandline.option('expand-var') and not option.empty? then + if option == '*' then + init_kpse.list_expansions() + else + puts init_kpse.expand_var(option) + end + elsif option = @commandline.option('show-path') and not option.empty? then + puts init_kpse.show_path(option) + elsif option = @commandline.option('var-value') and not option.empty? then + if option == '*' then + init_kpse.list_variables() + else + puts init_kpse.expand_var(option) + end + elsif @commandline.arguments.size > 0 then + kpse = init_kpse + @commandline.arguments.each do |option| + puts kpse.find_file(option) + end + else + help + end + end + + def analyze + pattern = @commandline.argument('first') + strict = @commandline.option('strict') + sort = @commandline.option('sort') + delete = @commandline.option('delete') and @commandline.option('force') + init_kpse.analyze_files(pattern, strict, sort, delete) + end + +end + +logger = Logger.new(banner.shift) +commandline = CommandLine.new + +# kpsewhich compatible options + +commandline.registervalue('expand-braces','') +commandline.registervalue('expand-path','') +commandline.registervalue('expand-var','') +commandline.registervalue('show-path','') +commandline.registervalue('var-value','') + +commandline.registervalue('engine','') +commandline.registervalue('progname','') +commandline.registervalue('format','') + +# additional goodies + +commandline.registervalue('rootpath','') +commandline.registervalue('treepath','') +commandline.registervalue('sort','') + +commandline.registerflag('diskcache') +commandline.registerflag('renewcache') +commandline.registerflag('strict') +commandline.registerflag('delete') +commandline.registerflag('force') + +commandline.registeraction('analyze') + +# general purpose options + +commandline.registerflag('verbose') +commandline.registeraction('help') +commandline.registeraction('version') + +commandline.expand + +Commands.new(commandline,logger,banner).send(commandline.action || 'main') -- cgit v1.2.3