diff --git a/lib/Card.rb b/lib/Card.rb new file mode 100644 index 0000000..a07e84e --- /dev/null +++ b/lib/Card.rb @@ -0,0 +1,36 @@ +class Card + attr_accessor :headword + def initialize(headword) + @headword = headword + @entries = {} + end + def <=> (other) + @headword <=> other.headword + end + def parse_from_dsl(line) + trn = /\[trn\](.*?)\[\/trn\]/.match(line)[1] + line.scan(/\{\{desc\}\}(.*?)\{\{\/desc\}\}/) { |desc| + add(trn, desc[0]) + } + end + def add(value, desc) + descs = (@entries[value] ||= []) + descs << desc unless descs.include?(desc) + end + def print_out(out) + out.puts @headword + @entries.keys.sort.each { |k| + out.print "\t[m1]" + if ($separator && @entries.size > 1) + out.print "#{$separator} " + end + initial_descr_dot = if (@entries[k] && @entries[k].size > 1) + "[m2]#{$DESC_DOT}" + else + "[m2]" + end + + out.puts "[trn]#{k}[/trn] [c darkgray]#{initial_descr_dot} #{@entries[k].uniq.sort.collect{|e| '{{desc}}' + e.to_s + '{{/desc}}'}.join(' [m2]' + $DESC_DOT + ' ')}[/c][/m]" + } + end +end diff --git a/lib/Dictionary.rb b/lib/Dictionary.rb new file mode 100644 index 0000000..e924ff1 --- /dev/null +++ b/lib/Dictionary.rb @@ -0,0 +1,93 @@ +class Dictionary + attr_accessor :name, :index_lang, :content_lang + def initialize + self.name = name + self.index_lang = index_lang + self.content_lang = content_lang + @cards = {} + end + def add(key, value, desc) + key.strip! + value.strip! + desc.strip! + if desc.empty? + $stderr.puts "ERROR: empty/missing dictionary description" + exit + end + (@cards[key] ||= Card.new(key)).add(value, desc) + end + def add_card(card) + if @cards[card.headword] + $stderr.puts "such card already exists: #{card.inspect}" + exit + else + @cards[card.headword] = card + end + end + def self.load_from_dsl(file) + d = Dictionary.new + if (file.gets =~ /^(?:\xEF\xBB\xBF)?#NAME\s*"(.*)"\s*$/) + d.name = $1 + else + $stderr.puts "\#NAME is not the first line in the DSL file" + exit + end + + if (file.gets =~ /^#INDEX_LANGUAGE\s*"(.*)"\s*$/) + d.index_lang = $1 + else + $stderr.puts "\#INDEX_LANGUAGE is not the second line in the DSL file" + exit + end + + if (file.gets =~ /^#CONTENTS_LANGUAGE\s*"(.*)"\s*$/) + d.content_lang = $1 + else + $stderr.puts "\#CONTENTS_LANGUAGE is not the third line in the DSL file" + exit + end + + card = nil + while (line = file.gets) + next if line.strip.empty? + line.rstrip! + if (line =~ /^(\S.*)$/) # headword + card = Card.new($1) + d.add_card(card) + elsif (line =~ /^\s/) # card body + card.parse_from_dsl(line) + else + $stderr.puts "Wrong line: #{line}" + exit + end + end + d + end + def check_valid + if name && index_lang && content_lang + # everything's fine + else + $stderr.puts "Required Dictionary Info is missing" + exit + end + end + def print_out(out_name) + check_valid + + out = File.open(out_name, 'w') + + # Dictionary Header + out.print "\xEF\xBB\xBF" + out.puts "\#NAME \"#{name}\"" + out.puts "\#INDEX_LANGUAGE \"#{index_lang}\"" + out.puts "\#CONTENTS_LANGUAGE \"#{content_lang}\"" + + @cards.values.sort.each { |card| + card.print_out(out) + } + + out.close + $stderr.puts "File #{out_name} written...." + $stderr.puts "Total number of headwords: #{@cards.size}" + end +end diff --git a/txt2dsl.rb b/txt2dsl.rb new file mode 100644 index 0000000..d3d56a5 --- /dev/null +++ b/txt2dsl.rb @@ -0,0 +1,71 @@ +# TODO: +# 1. check for key, value, desc validity +# 2. check for empty cards + +require 'optparse' +require 'fileutils' + +require File.expand_path('../lib/Dictionary', __FILE__) +require File.expand_path('../lib/Card', __FILE__) + +$IN = [] +$OUT = "" +$DOT = "*" +$DESC_DOT = "-" + +$separotor = nil +opts = OptionParser.new +opts.on("-i FILE", "--in FILE", "input file to convert", String) {|val| $IN << val } +opts.on("-o FILE", "--out FILE", "file to generate or append to", String) { |val| + if ($OUT.empty?) + $OUT = val + else + $stderr.puts "Error: output file can be defined only once!\n\n" + $stderr.puts opts + exit + end +} +opts.on("-s", "start each line with a separator") { $separator = $DOT } +opts.on_tail("-h", "--help", "Show this message") do + $stderr.puts opts + exit +end +rest = opts.parse(ARGV) + +if ($IN.size == 0 || $OUT.size == 0) + $stderr.puts opts + exit +end + +d = nil +if File.exist?($OUT) + back = $OUT + ".bak" + FileUtils.copy($OUT, back) + $stderr.puts "Made backup copy: #{back}" + File.open($OUT, 'rb') { |f| + d = Dictionary.load_from_dsl(f) + } +end + +unless d + d = Dictionary.new + d.name = "Initial" + d.index_lang = "English" + d.content_lang = "Russian" +end + +$IN.each { |file_name| + desc = "" + File.foreach(file_name) { |line| + if line =~ /^(?:\xEF\xBB\xBF)?#\s*[Dd]escription\s*(.*)$/ + desc = $1.strip + elsif line =~ /^\s*$/ + # ignore + elsif line =~ /^(.*?):(.*)$/ + key, value = $1, $2 + d.add(key, value, desc) + end + } +} + +d.print_out($OUT)