diff options
Diffstat (limited to 'scripts')
-rw-r--r-- | scripts/context/perl/texexec.pl | 4 | ||||
-rw-r--r-- | scripts/context/ruby/ctxtools.rb | 406 | ||||
-rw-r--r-- | scripts/context/ruby/textools.rb | 81 |
3 files changed, 487 insertions, 4 deletions
diff --git a/scripts/context/perl/texexec.pl b/scripts/context/perl/texexec.pl index 9a04e3660..0cd31ff4b 100644 --- a/scripts/context/perl/texexec.pl +++ b/scripts/context/perl/texexec.pl @@ -870,7 +870,7 @@ $OutputFormats{dvipdfm} = "dvipdfm"; $OutputFormats{dvipdfmx} = "dvipdfmx"; $OutputFormats{xetex} = "xetex"; -my @ConTeXtFormats = ( "nl", "en", "de", "cz", "uk", "it", "ro"); +my @ConTeXtFormats = ( "nl", "en", "de", "cz", "uk", "it", "ro", "xx"); sub SetInterfaces { my ( $short, $long, $full ) = @_; @@ -2808,7 +2808,7 @@ sub show_version_info { print " tex : $texengine\n" ; print " context : ver: $contextversion\n" ; print " cont-en : $type\n" ; - foreach my $a (qw(cz de it nl ro uk)) { + foreach my $a (qw(cz de it nl ro uk xx)) { my $test = `$kpsewhich -format='fmt' cont-$a`; if (defined $test && $test) { $Format = 'cont-' . $a; diff --git a/scripts/context/ruby/ctxtools.rb b/scripts/context/ruby/ctxtools.rb index 5a0dde13b..5b05474a0 100644 --- a/scripts/context/ruby/ctxtools.rb +++ b/scripts/context/ruby/ctxtools.rb @@ -10,7 +10,7 @@ # todo: move scite here -banner = ['CtxTools', 'version 1.2.0', '2004/2005', 'PRAGMA ADE/POD'] +banner = ['CtxTools', 'version 1.2.1', '2004/2005', 'PRAGMA ADE/POD'] unless defined? ownpath ownpath = $0.sub(/[\\\/][a-z0-9\-]*?\.rb/i,'') @@ -478,7 +478,7 @@ class Commands filesize = FileTest.size(filename) File.delete(filename) rescue - report("problematic : #{filename}") + report("problematic : #{filename}") else if FileTest.file?(filename) then $persistentfiles += 1 @@ -704,6 +704,405 @@ class Commands end +# This script is used to generate hyphenation pattern files +# that suit ConTeXt. One reason for independent files is that +# over the years too many uncommunicated chabges took place +# as well that inconsistency in content, naming, and location +# in the texmf tree takes more time than I'm willing to spend +# on it. Pattern files are normally shipped for LaTeX (and +# partially plain). A side effect of independent files is that +# we can make them encoding independent. + +class Language + + include CommandBase + + def initialize(commandline=nil, language='en', filenames=nil, encoding='ec') + @commandline= commandline + @language = language + @filenames = filenames + @remapping = Array.new + @encoding = encoding + @data = '' + @read = '' + preload_accents() + case @encoding.downcase + when 't1', 'ec', 'cork' then preload_vector('ec') + end + end + + def report(str) + if @commandline then + @commandline.report(str) + else + puts("#{str}\n") + end + end + + def remap(from, to) + @remapping.push([from,to]) + end + + def load(filenames=@filenames) + begin + if filenames then + @filenames = [filenames].flatten + @filenames.each do |filename| + begin + if filename = located(filename) then + data = IO.read(filename) + @data += data.gsub(/\%.*$/, '') + data.gsub!(/(\\patterns|\\hyphenation)\s*\{.*/mo) do '' end + @read += "\n% preamble of file #{filename}\n\n#{data}\n" + else + report("file #{filename} is not found") + end + rescue + report("file #{filename} is not readable") + else + report("file #{filename} is loaded") + end + # @data.gsub!(/\s\\[nc]\{(.*?)\}\s/o) do $1 end + end + end + rescue + end + end + + def valid? + ! @data.empty? + end + + 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] + end + end + report("#{n} changes in patterns and exceptions") + return n + else + return 0 + end + end + + def comment(str) + str.gsub!(/^\n/o, '') + str.chomp! + if @commandline.option('xml') then + "<!-- #{str.strip} -->\n\n" + else + "% #{str.strip}\n\n" + end + end + + def content(tag, str) + lst = str.split(/\s+/) + lst.collect! do |l| + l.strip + end + if lst.length>0 then + lst = "\n#{lst.join("\n")}\n" + else + lst = "" + end + if @commandline.option('xml') then + lst.gsub!(/\[(.*?)\]/o) do + "&#{$1};" + end + "<#{tag}>#{lst}</#{tag}>\n\n" + else + "\\#{tag} \{#{lst}\}\n\n" + end + end + + def banner + if @commandline.option('xml') then + "<?xml version='1.0' standalone='yes' ?>\n\n" + end + end + + def save + xml = @commandline.option("xml") + + patname = "lang-#{@language}.pat" + hypname = "lang-#{@language}.hyp" + rmename = "lang-#{@language}.rme" + logname = "lang-#{@language}.log" + + @data.gsub!(/\\[nc]\{(.+?)\}/) do $1 end + @data.gsub!(/\{\}/) do '' end + @data.gsub!(/\n+/mo) do "\n" end + @read.gsub!(/\n+/mo) do "\n" end + + begin + if f = File.open(logname,'w') then + report("saving #{@remapping.length} remap patterns in #{logname}") + @remapping.each do |m| + f.puts("#{m[0].inspect} => #{m[1]}\n") + end + f.close + end + rescue + end + + begin + if f = File.open(rmename,'w') then + data = @read.dup + data.gsub!(/(\s*\n\s*)+/mo, "\n") + f << comment("comment copied from public hyphenation files}") + f << comment("source of data: #{@filenames.join(' ')}") + f << comment("begin original comment") + f << "#{data}\n" + f << comment("end original comment") + f.close + report("comment saved in file #{rmename}") + else + report("file #{rmename} is not writable") + end + rescue + end + + begin + if f = File.open(patname,'w') then + data = '' + @data.scan(/\\patterns\s*\{\s*(.*?)\s*\}/m) do + report("merging patterns") + data += $1 + "\n" + end + data.gsub!(/(\s*\n\s*)+/mo, "\n") + f << banner + f << comment("context pattern file, see #{rmename} for original comment") + f << comment("source of data: #{@filenames.join(' ')}") + f << comment("begin pattern data") + f << content('patterns', data) + f << comment("end pattern data") + f.close + report("patterns saved in file #{patname}") + else + report("file #{patname} is not writable") + end + rescue + report("problems with file #{patname}") + end + + begin + if f = File.open(hypname,'w') then + data = '' + @data.scan(/\\hyphenation\s*\{\s*(.*?)\s*\}/m) do + report("merging exceptions") + data += $1 + "\n" + end + data.gsub!(/(\s*\n\s*)+/mo, "\n") + f << banner + f << comment("context hyphenation file, see #{rmename} for original comment") + f.<< comment("source of data: #{@filenames.join(' ')}") + f.<< comment("begin hyphenation data") + f << content('hyphenation', data) + f.<< comment("end hyphenation data") + f.close + report("exceptions saved in file #{hypname}") + else + report("file #{hypname} is not writable") + end + rescue + report("problems with file #{hypname}") + end + end + + def process + load + if valid? then + convert + save + else + report("aborted due to missing files") + end + end + + def Language::generate(commandline, language='', filenames='', encoding='ec') + if ! language.empty? && ! filenames.empty? then + commandline.report("processing language #{language}") + commandline.report("") + language = Language.new(commandline,language,filenames,encoding) + language.load + language.convert + language.save + commandline.report("") + end + end + + private + + def located(filename) + begin + filename = `kpsewhich -progname=context #{filename}`.chomp + if FileTest.file?(filename) then + report("using file #{filename}") + return filename + else + report("file #{filename} is not present") + return nil + end + rescue + report("file #{filename} cannot be located using kpsewhich") + return nil + end + end + + def preload_accents + + begin + if filename = located("enco-acc.tex") then + if data = IO.read(filename) then + report("preloading accent conversions") + data.scan(/\\defineaccent\s*\\*(.+?)\s*\{*(.+?)\}*\s*\{\\(.+?)\}/o) do + one, two, three = $1, $2, $3 + one.gsub!(/[\`\~\!\^\*\_\-\+\=\:\;\"\'\,\.\?]/o) do + "\\#{one}" + end + remap(/\\#{one} #{two}/, "[#{three}]") + remap(/\\#{one}#{two}/, "[#{three}]") unless one =~ /[a-zA-Z]/o + remap(/\\#{one}\{#{two}\}/, "[#{three}]") + end + end + end + rescue + end + + end + + def preload_vector(encoding='') + + # funny polish + + case @language + when 'pl' then + remap(/\/a/, "[aogonek]") ; remap(/\/A/, "[Aogonek]") + remap(/\/c/, "[cacute]") ; remap(/\/C/, "[Cacute]") + remap(/\/e/, "[eogonek]") ; remap(/\/E/, "[Eogonek]") + remap(/\/l/, "[lstroke]") ; remap(/\/L/, "[Lstroke]") + remap(/\/n/, "[nacute]") ; remap(/\/N/, "[Nacute]") + remap(/\/o/, "[oacute]") ; remap(/\/O/, "[Oacute]") + remap(/\/s/, "[sacute]") ; remap(/\/S/, "[Sacute]") + remap(/\/x/, "[zacute]") ; remap(/\/X/, "[Zacute]") + remap(/\/z/, "[zdotaccent]") ; remap(/\/Z/, "[Zdotaccent]") + when 'sl' then + remap(/\"c/,"[ccaron]") ; remap(/\"C/,"[Ccaron]") + remap(/\"s/,"[scaron]") ; remap(/\"S/,"[Scaron]") + remap(/\"z/,"[zcaron]") ; remap(/\"Z/,"[Zcaron]") + when 'da' then + remap(/X/, "[aeligature]") + remap(/Y/, "[ostroke]") + remap(/Z/, "[aring]") + when 'ca' then + remap(/\\c\{.*?\}/, "") + when 'de', 'deo' then + remap(/\\c\{.*?\}/, "") + remap(/\\n\{\}/, "") + remap(/\\3/, "[ssharp]") + remap(/\\9/, "[ssharp]") + remap(/\"a/, "[adiaeresis]") + remap(/\"o/, "[odiaeresis]") + remap(/\"u/, "[udiaeresis]") + when 'fr' then + remap(/\\ae/, "[adiaeresis]") + remap(/\\oe/, "[odiaeresis]") + when 'la' then + # \lccode`'=`' somewhere else, todo + remap(/\\c\{.*?\}/, "") + remap(/\\a\s*/, "[aeligature]") + remap(/\\o\s*/, "[oeligature]") + else + end + + if ! encoding.empty? then + begin + filename = `kpsewhich -progname=context enco-#{encoding}.tex` + if data = IO.read(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}]") + end + end + rescue + end + end + + end + +end + +class Commands + + include CommandBase + + public + + @@languagedata = Hash.new + + def patternfiles + language = @commandline.argument('first') + if ! language.empty? then + if language == 'all' then + languages = @@languagedata.keys.sort + elsif @@languagedata.key?(language) then + languages = [language] + else + languages = [] + end + languages.each do |language| + files = @@languagedata[language][0] || '' + encoding = @@languagedata[language][1] || '' + Language::generate(self,language,files,encoding) + end + end + end + + private + + @@languagedata['ba' ] = [['bahyph.tex'], 'ec'] + @@languagedata['ca' ] = [['cahyph.tex'], 'ec'] + @@languagedata['cy' ] = [['cyhyph.tex'], 'ec'] + @@languagedata['cz' ] = [['czhyphen.tex','czhyphen.ex'], 'ec'] + @@languagedata['de' ] = [['dehyphn.tex'], 'ec'] + @@languagedata['deo'] = [['dehypht.tex'], 'ec'] + @@languagedata['da' ] = [['dkspecial.tex','dkcommon.tex'], 'ec'] + # elhyph.tex + @@languagedata['es' ] = [['eshyph.tex'], 'ec'] + @@languagedata['fi' ] = [['ethyph.tex'], 'ec'] + @@languagedata['fi' ] = [['fihyph.tex'], 'ec'] + @@languagedata['fr' ] = [['frhyph.tex'], 'ec'] + # ghyphen.readme ghyph31.readme grphyph + @@languagedata['hr' ] = [['hrhyph.tex'], 'ec'] + @@languagedata['hu' ] = [['huhyphn.tex'], 'ec'] + @@languagedata['en' ] = [['hyphen.tex'], 'default'] + # inhyph.tex + @@languagedata['is' ] = [['ishyph.tex'], 'ec'] + @@languagedata['it' ] = [['ithyph.tex'], 'ec'] + @@languagedata['la' ] = [['lahyph.tex'], 'ec'] + # mnhyph + @@languagedata['nl' ] = [['nehyph96.tex'], 'ec'] + @@languagedata['no' ] = [['nohyph.tex'], 'ec'] + # oldgrhyph.tex + @@languagedata['pl' ] = [['plhyph.tex'], 'ec'] + @@languagedata['pt' ] = [['pthyph.tex'], 'ec'] + @@languagedata['ro' ] = [['rohyph.tex'], 'ec'] + @@languagedata['sl' ] = [['sihyph.tex'], 'ec'] + @@languagedata['sk' ] = [['skhyphen.tex','skhyphen.ex'], 'ec'] + # sorhyph.tex / upper sorbian + # srhyphc.tex / cyrillic + @@languagedata['sv' ] = [['svhyph.tex'], 'ec'] + @@languagedata['tr' ] = [['tkhyph.tex'], 'ec'] + @@languagedata['uk' ] = [['ukhyphen.tex'], 'default'] + +end + logger = EXA::ExaLogger.new(banner.shift) commandline = CommandLine.new @@ -722,6 +1121,8 @@ commandline.registeraction('documentation', 'generate documentation file [--type commandline.registeraction('filterpages') # no help, hidden temporary feature +commandline.registeraction('patternfiles', 'generate pattern files [languagecode|all]') + commandline.registeraction('help') commandline.registeraction('version') @@ -731,6 +1132,7 @@ commandline.registervalue('type','') # commandline.registerflag('force') commandline.registerflag('pipe') commandline.registerflag('all') +commandline.registerflag('xml') commandline.expand diff --git a/scripts/context/ruby/textools.rb b/scripts/context/ruby/textools.rb index 6c8b08813..a1880890d 100644 --- a/scripts/context/ruby/textools.rb +++ b/scripts/context/ruby/textools.rb @@ -531,6 +531,86 @@ class Commands end end + public + + def showfont + + file = @commandline.argument('first') + + if file.empty? then + report('provide filename') + else + file.sub!(/\.afm$/,'') + begin + report("analyzing afm file #{file}.afm") + file = `kpsewhich #{file}.afm`.chomp + rescue + report('unable to run kpsewhich') + return + end + + names = Array.new + + if FileTest.file?(file) then + File.new(file).each do |line| + if line.match(/^C\s*([\-\d]+)\s*\;.*?\s*N\s*(.+?)\s*\;/o) then + names.push($2) + end + end + ranges = names.size + report("number of glyphs: #{ranges}") + ranges = ranges/256 + 1 + report("number of subsets: #{ranges}") + file = File.basename(file).sub(/\.afm$/,'') + tex = File.open("textools.tex",'w') + map = File.open("textools.map",'w') + tex.puts("\\starttext\n") + tex.puts("\\loadmapfile[textools.map]\n") + for i in 1..ranges do + rfile = "#{file}-range-#{i}" + report("generating enc file #{rfile}.enc") + flushencoding("#{rfile}", (i-1)*256, i*256-1, names) + # catch console output + report("generating tfm file #{rfile}.tfm") + mapline = `afm2tfm #{file}.afm -T #{rfile}.enc #{rfile}.tfm` + # more robust replacement + mapline = "#{rfile} <#{rfile}.enc <#{file}.pfb" + # final entry in map file + mapline = "#{mapline} <#{file}.pfb" + map.puts("#{mapline}\n") + tex.puts("\\showfont[#{rfile}][unknown]\n") + end + tex.puts("\\stoptext\n") + report("generating map file textools.map") + report("generating tex file textools.tex") + map.close + tex.close + else + report("invalid file #{file}") + end + end + + end + + private + + def flushencoding (file, from, to, names) + n = 0 + out = File.open("#{file}.enc",'w') + out.puts("/#{file.gsub(/\-/,'')} [\n") + for i in from..to do + if names[i] then + n += 1 + out.puts("/#{names[i]}\n") + else + out.puts("/.notdef\n") + end + end + out.puts("] def\n") + out.close + return n + end + private # specific def movefiles(from_path,to_path,suffix,&block) @@ -652,6 +732,7 @@ commandline.registeraction('fixtexmftrees' , '[texmfroot] [--force]') commandline.registeraction('replace' , 'filename [--force]') commandline.registeraction('downcasefilenames', '[--recurse] [--force]') # not yet documented commandline.registeraction('stripformfeeds' , '[--recurse] [--force]') # not yet documented +commandline.registeraction('showfont' , 'filename') commandline.registeraction('help') commandline.registeraction('version') |