diff options
Diffstat (limited to 'Master/texmf-dist/source/generic/hyph-utf8/lib/tex/hyphen/language.rb')
-rw-r--r-- | Master/texmf-dist/source/generic/hyph-utf8/lib/tex/hyphen/language.rb | 364 |
1 files changed, 364 insertions, 0 deletions
diff --git a/Master/texmf-dist/source/generic/hyph-utf8/lib/tex/hyphen/language.rb b/Master/texmf-dist/source/generic/hyph-utf8/lib/tex/hyphen/language.rb new file mode 100644 index 00000000000..3d3437d74b5 --- /dev/null +++ b/Master/texmf-dist/source/generic/hyph-utf8/lib/tex/hyphen/language.rb @@ -0,0 +1,364 @@ +require 'yaml' +require 'hydra' +require 'byebug' unless ENV['RACK_ENV'] == "production" + +require_relative 'path' + +class String + def superstrip + strip.gsub /%.*$/, '' + end + + def supersplit + strip.gsub(/\s+/m,"\n").split("\n") + end + + def safe + gsub /[\s-]/, '' + end + + def titlecase + split.map(&:capitalize).join(' ') + end +end + +module TeX + module Hyphen + class InvalidMetadata < StandardError; end + class NoAuthor < InvalidMetadata; end + class NoLicence < InvalidMetadata; end + + include PATH + + class Author + def initialize(name,surname,email,contacted1,contacted2) + @name = name + @surname = surname + @email = email + # this mostly means if email has been recently checked + @contacted1 = contacted1 + # this means if we made more cooperation with author, + # exchanging patches etc. + @contacted2 = contacted2 + end + + attr_reader :name, :surname, :email + + def self.authors + @@authors ||= YAML::load File.read File.expand_path 'authors.yml', __dir__ + end + + def self.all + authors.values + end + + def self.[] a + authors[a] + end + end + + class Language + attr_reader :bcp47 + + @@eohmarker = '=' * 42 + + def iso639 + @bcp47.split('-').first + end + + # FIXME Find something better than all that extract_metadata unless @blah nonsens + def babelname + extract_metadata unless @babelname + @babelname + end + + def description + extract_metadata unless @description + @description + end + + def use_old_loader + extract_metadata unless @use_old_loader + @use_old_loader + end + + def use_old_patterns_comment + extract_metadata unless @use_old_patterns_comment + @use_old_patterns_comment + end + + def legacy_patterns + extract_metadata unless @legacy_patterns + @legacy_patterns + end + + def message + extract_metadata unless @message + @message + end + + def known_bugs + extract_metadata unless @known_bugs + @known_bugs + end + + def initialize(bcp47 = nil) + @bcp47 = bcp47 + end + + def self.languages + @@languages ||= Dir.glob(File.join(PATH::TEX, 'hyph-*.tex')).inject [] do |languages, texfile| + bcp47 = texfile.gsub /^.*\/hyph-(.*)\.tex$/, '\1' + # languages << [bcp47, Language.new(bcp47)] + languages << [bcp47, nil] + end.to_h + end + @@languages = Language.languages + + def self.all + @@all ||= languages.map do |bcp47, language| + next if bcp47 == 'sr-cyrl' # FIXME Remove later + @@languages[bcp47] ||= Language.new(bcp47) + end.compact + end + + def self.all_by_iso639 + all.inject(Hash.new) do |maintags, language| + (maintags[language.iso639] ||= Array.new) << language + maintags + end + end + + def self.find_by_bcp47(bcp47) + languages[bcp47] + end + + def private_use? + @bcp47.length == 3 || @bcp47[3] == '-' and @bcp47[0] == 'q' and ('a'..'t').include? @bcp47[1] + end + + # TODO This should probably become “macrolanguage name” or something similar + # @@displaynames = { + # 'el' => 'Greek', + # 'nb' => 'Norwegian', + # 'nn' => 'Norwegian', + # 'sh' => 'Serbian', + # } + + def licences + extract_metadata unless @licences + @licences + end + + def lefthyphenmin + extract_metadata unless @lefthyphenmin + @lefthyphenmin + end + + def righthyphenmin + extract_metadata unless @righthyphenmin + @righthyphenmin + end + + # Strictly speaking a misnomer, because grc-x-ibycus should also return true. + # But useful for a number of apostrophe-related routines + def isgreek? + ['grc', 'el-polyton', 'el-monoton'].include? @bcp47 + end + + def serbian? + @bcp47 =~ /^sh-/ + end + + def italic? + ['it', 'pms', 'rm'].include? @bcp47 + end + + def has_apostrophes? + begin + !isgreek? && patterns.any? { |p| p =~ /'/ } + rescue Errno::ENOENT + false + end + end + + def has_hyphens? + begin + patterns.any? { |p| p =~ /-/ } + rescue Errno::ENOENT + false + end + end + + def extract_apostrophes + plain, with_apostrophe = Array.new, nil + + patterns.each do |pattern| + plain << pattern + if pattern =~ /'/ && !isgreek? + pattern_with_apostrophe = pattern.gsub(/'/,"’") + plain << pattern_with_apostrophe + (with_apostrophe ||= []) << pattern_with_apostrophe + end + end + + { plain: plain, with_apostrophe: with_apostrophe } + end + + def extract_characters # FIXME Turkish and others iİ; check Church Slavonic + characters = Array.new + + characters_indexes = patterns.join.gsub(/[.0-9]/,'').unpack('U*').sort.uniq + characters_indexes.each do |c| + ch = [c].pack('U') + characters << ch + ch.upcase + characters << "’’" if ch == "'" && !isgreek? + end + + characters + end + + def comments_and_licence # Major TODO extract everything into YAML, and write .yml + @comments_and_licence ||= readtexfile.gsub(/(.*)\\patterns.*/m,'\1') + end + + def authors + extract_metadata unless @authors + @authors + end + + def github_link + sprintf 'https://github.com/hyphenation/tex-hyphen/tree/master/hyph-utf8/tex/generic/hyph-utf8/patterns/tex/hyph-%s.tex', @bcp47 + end + + def <=>(other) + # TODO Remove when practical + a = self.babelname + b = other.babelname + + if a == 'serbian' && b == 'serbianc' + return -1 + elsif a == 'serbianc' && b == 'serbian' + return 1 + end + + self.bcp47 <=> other.bcp47 + end + + @@texfile = Hash.new + def readtexfile(bcp47 = @bcp47) + begin + @@texfile[bcp47] ||= File.read(File.join(PATH::TEX, sprintf('hyph-%s.tex', bcp47))) + rescue Errno::ENOENT + @@texfile[bcp47] = "" + end + end + + def patterns + @patterns ||= if @bcp47 == 'eo' then + readtexfile.superstrip. + gsub(/.*\\patterns\s*\{(.*)\}.*/m,'\1'). + # + gsub(/\\adj\{(.*?)\}/m,'\1a. \1aj. \1ajn. \1an. \1e.'). + gsub(/\\nom\{(.*?)\}/m,'\1a. \1aj. \1ajn. \1an. \1e. \1o. \1oj. \1ojn. \1on.'). + gsub(/\\ver\{(.*?)\}/m,'\1as. \1i. \1is. \1os. \1u. \1us.'). + # + supersplit + else + readtexfile(if ['nb', 'nn'].include? @bcp47 then 'no' else @bcp47 end).superstrip. + gsub(/.*\\patterns\s*\{(.*?)\}.*/m,'\1'). + supersplit + end + end + + def exceptions + unless @exceptions + if readtexfile.superstrip.index('\hyphenation') + @exceptions = readtexfile.superstrip.gsub(/.*\\hyphenation\s*\{(.*?)\}.*/m,'\1').supersplit + if @exceptions != "" + @hyphenation = @exceptions.inject [] do |exceptions, exception| + # byebug unless exception + exceptions << [exception.gsub('-', ''), exception] + end.to_h + else + @hyphenation = { } + end + else + @exceptions = "" + @hyphenation = { } + end + end + + @exceptions + end + + def hyphenate(word) + exceptions + return @hyphenation[word] if @hyphenation[word] # FIXME Better name + + unless @hydra + begin + # byebug + metadata = extract_metadata + @hydra = Hydra.new patterns, :lax, '', metadata + rescue InvalidMetadata + @hydra = Hydra.new patterns + end + end + @hydra.showhyphens(word) + end + + def extract_metadata + header = "" + File.read(File.join(PATH::TEX, sprintf('hyph-%s.tex', @bcp47))).each_line do |line| + break if line =~ /\\patterns|#{@@eohmarker}/ + header += line.gsub(/^% /, '').gsub(/%.*/, '') + end + begin + metadata = YAML::load header + raise InvalidMetadata unless metadata.is_a? Hash + rescue Psych::SyntaxError + raise InvalidMetadata + end + + @name = metadata.dig('language', 'name') + @lefthyphenmin = metadata.dig('hyphenmins', 'typesetting', 'left') || metadata.dig('hyphenmins', 'generation', 'left') + @righthyphenmin = metadata.dig('hyphenmins', 'typesetting', 'right') || metadata.dig('hyphenmins', 'generation', 'right') + # FIXME That’s not nice + if respond_to? :synonyms + @synonyms = metadata.dig('texlive', 'synonyms') || [] + @encoding = metadata.dig('texlive', 'encoding') + end + @message = metadata.dig('texlive', 'message') + @legacy_patterns = metadata.dig('texlive', 'legacy_patterns') + @use_old_loader = metadata.dig('texlive', 'use_old_loader') + @use_old_patterns_comment = metadata.dig('texlive', 'use_old_patterns_comment') + @description = metadata.dig('texlive', 'description') + @babelname = metadata.dig('texlive', 'babelname') + @package = metadata.dig('texlive', 'package') + licences = metadata.dig('licence') + raise NoLicence unless licences + licences = [licences] unless licences.is_a? Array + @licences = licences.map do |licence| + raise bcp47 if licence.is_a? String + next if licence.values == [nil] + licence.dig('name') || 'custom' + end.compact + authors = metadata.dig('authors') + if authors + @authors = authors.map do |author| + author['name'] + end + else + @authors = nil + raise NoAuthor.new # FIXME + end + @known_bugs = metadata.dig('known_bugs') + + # raise NoAuthor unless @authors && @authors.count > 0 # TODO Later ;-) AR 2018-09-13 + + metadata + end + end + end +end |