summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/scripts/context/ruby/ctxtools.rb
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/scripts/context/ruby/ctxtools.rb')
-rw-r--r--Master/texmf-dist/scripts/context/ruby/ctxtools.rb1251
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