logaling-command 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGES ADDED
@@ -0,0 +1,18 @@
1
+ = 0.1.2 / 2012-01-30
2
+
3
+ * 英和 / 和英 辞書のインポートができるようになりました。他プロジェクトの用語集をインポートする `loga import` と同じ手順でインポートすることができます。
4
+
5
+ * 出力結果が長くなった場合に、ページングが出来るようになりました。
6
+
7
+ * `loga show` コマンドが追加されました。指定した用語集内の用語を一覧する為のコマンドです。
8
+
9
+ * `loga list` コマンドが追加されました。登録されている用語集を一覧するためのコマンドです。
10
+
11
+ * `loga update` コマンド利用時に備考のみの変更ができるようになりました。(KitaitiMakoto さん)
12
+
13
+ * インデックスのタイミングと方式を変更したので、 `loga lookup` の結果表示速度が改善されました。
14
+
15
+ * 用語の登録 / 更新時の重複チェックを 用語集ファイルではなくインデックスしたものでチェックするように修正しました。
16
+
17
+ * loga lookup 時に自分のプロジェクトの用語集名が、より分かり易くなるように色付けを改良しました。
18
+
@@ -19,10 +19,9 @@ require 'thor'
19
19
  require 'rainbow'
20
20
  require "logaling/repository"
21
21
  require "logaling/glossary"
22
- require "logaling/external_glossary"
23
22
 
24
23
  class Logaling::Command < Thor
25
- VERSION = "0.1.1"
24
+ VERSION = "0.1.2"
26
25
  LOGALING_CONFIG = '.logaling'
27
26
 
28
27
  map '-a' => :add,
@@ -33,6 +32,8 @@ class Logaling::Command < Thor
33
32
  '-n' => :new,
34
33
  '-r' => :register,
35
34
  '-U' => :unregister,
35
+ '-L' => :list,
36
+ '-s' => :show,
36
37
  '-v' => :version
37
38
 
38
39
  class_option "glossary", type: :string, aliases: "-g"
@@ -59,6 +60,7 @@ class Logaling::Command < Thor
59
60
  desc 'import', 'Import external glossary'
60
61
  method_option "list", type: :boolean, default: false
61
62
  def import(external_glossary=nil)
63
+ require "logaling/external_glossary"
62
64
  Logaling::ExternalGlossary.load
63
65
  if options["list"]
64
66
  Logaling::ExternalGlossary.list.each {|glossary| say "#{glossary.name.bright} : #{glossary.description}" }
@@ -118,6 +120,13 @@ class Logaling::Command < Thor
118
120
 
119
121
  desc 'add [SOURCE TERM] [TARGET TERM] [NOTE(optional)]', 'Add term to glossary.'
120
122
  def add(source_term, target_term, note='')
123
+ config = load_config_and_merge_options
124
+ repository.index
125
+
126
+ if repository.bilingual_pair_exists?(source_term, target_term, config["glossary"])
127
+ raise Logaling::TermError, "term '#{source_term}: #{target_term}' already exists in '#{config["glossary"]}'"
128
+ end
129
+
121
130
  glossary.add(source_term, target_term, note)
122
131
  rescue Logaling::CommandFailed, Logaling::TermError => e
123
132
  say e.message
@@ -139,6 +148,13 @@ class Logaling::Command < Thor
139
148
 
140
149
  desc 'update [SOURCE TERM] [TARGET TERM] [NEW TARGET TERM], [NOTE(optional)]', 'Update term.'
141
150
  def update(source_term, target_term, new_target_term, note='')
151
+ config = load_config_and_merge_options
152
+ repository.index
153
+
154
+ if repository.bilingual_pair_exists_and_has_same_note?(source_term, new_target_term, note, config["glossary"])
155
+ raise Logaling::TermError, "term '#{source_term}: #{new_target_term}' already exists in '#{config["glossary"]}'"
156
+ end
157
+
142
158
  glossary.update(source_term, target_term, new_target_term, note)
143
159
  rescue Logaling::CommandFailed, Logaling::TermError => e
144
160
  say e.message
@@ -154,14 +170,20 @@ class Logaling::Command < Thor
154
170
 
155
171
  unless terms.empty?
156
172
  max_str_size = terms.map{|term| term[:source_term].size}.sort.last
173
+ run_pager
157
174
  terms.each do |term|
158
175
  target_string = "#{term[:target_term].bright}"
159
176
  target_string << "\t# #{term[:note]}" unless term[:note].empty?
160
177
  if repository.glossary_counts > 1
161
- color = (term[:name] == config["glossary"]) ? :green : :cyan
162
- target_string << "\t(#{term[:name]})".color(color)
178
+ target_string << "\t"
179
+ glossary_name = "(#{term[:glossary_name]})"
180
+ if term[:glossary_name] == config["glossary"]
181
+ target_string << glossary_name.foreground(:white).background(:green)
182
+ else
183
+ target_string << glossary_name
184
+ end
163
185
  end
164
- source_string = term[:source_term].split(source_term).insert(1, source_term.dup.bright).join
186
+ source_string = term[:snipped_source_term].map{|word| word.is_a?(Hash) ? word[:keyword].bright : word }.join
165
187
  printf(" %-#{max_str_size+10}s %s\n", source_string, target_string)
166
188
  end
167
189
  else
@@ -176,6 +198,49 @@ class Logaling::Command < Thor
176
198
  say "logaling-command version #{Logaling::Command::VERSION}"
177
199
  end
178
200
 
201
+ desc 'show', 'Show terms in glossary.'
202
+ def show
203
+ required_options = {
204
+ "glossary" => "input glossary name '-g <glossary name>'",
205
+ "source-language" => "input source-language code '-S <source-language code>'",
206
+ "target-language" => "input target-language code '-T <target-language code>'"
207
+ }
208
+ config = load_config_and_merge_options(required_options)
209
+ repository.index
210
+ terms = repository.show_glossary(config["glossary"], config["source-language"], config["target-language"])
211
+ unless terms.empty?
212
+ run_pager
213
+ max_str_size = terms.map{|term| term[:source_term].size}.sort.last
214
+ terms.each do |term|
215
+ target_string = "#{term[:target_term]}"
216
+ target_string << "\t# #{term[:note]}" unless term[:note].empty?
217
+ printf(" %-#{max_str_size+10}s %s\n", term[:source_term], target_string)
218
+ end
219
+ else
220
+ "glossary <#{config['glossary']}> not found"
221
+ end
222
+
223
+ rescue Logaling::CommandFailed, Logaling::GlossaryDBNotFound => e
224
+ say e.message
225
+ end
226
+
227
+ desc 'list', 'Show glossary list.'
228
+ def list
229
+ repository.index
230
+ glossaries = repository.list
231
+ unless glossaries.empty?
232
+ run_pager
233
+ glossaries.each do |glossary|
234
+ printf(" %s\n", glossary)
235
+ end
236
+ else
237
+ "There is no registered glossary."
238
+ end
239
+
240
+ rescue Logaling::CommandFailed, Logaling::GlossaryDBNotFound => e
241
+ say e.message
242
+ end
243
+
179
244
  private
180
245
  def repository
181
246
  @repository ||= Logaling::Repository.new(LOGALING_HOME)
@@ -278,4 +343,32 @@ class Logaling::Command < Thor
278
343
  fp.puts "--target-language #{config['target-language']}" if config['target-language']
279
344
  end
280
345
  end
346
+
347
+ # http://nex-3.com/posts/73-git-style-automatic-paging-in-ruby
348
+ def run_pager
349
+ return if ::RUBY_PLATFORM =~ /win32/
350
+ return unless STDOUT.tty?
351
+
352
+ read, write = IO.pipe
353
+
354
+ unless Kernel.fork # Child process
355
+ STDOUT.reopen(write)
356
+ STDERR.reopen(write) if STDERR.tty?
357
+ read.close
358
+ write.close
359
+ return
360
+ end
361
+
362
+ # Parent process, become pager
363
+ STDIN.reopen(read)
364
+ read.close
365
+ write.close
366
+
367
+ ENV['LESS'] = 'FSRX' # Don't page if the input is short enough
368
+
369
+ # wait until we have input before we start the pager
370
+ Kernel.select [STDIN]
371
+ pager = ENV['PAGER'] || 'less'
372
+ exec pager rescue exec "/bin/sh", "-c", pager
373
+ end
281
374
  end
@@ -1,4 +1,5 @@
1
1
  # Copyright (C) 2011 Miho SUZUKI
2
+ # Copyright (C) 2012 Kouhei Sutou <kou@clear-code.com>
2
3
  #
3
4
  # This program is free software: you can redistribute it and/or modify
4
5
  # it under the terms of the GNU General Public License as published by
@@ -21,15 +22,14 @@ module Logaling
21
22
  description 'Debian JP Project (http://www.debian.or.jp/community/translate/)'
22
23
  source_language 'en'
23
24
  target_language 'ja'
25
+ output_format 'csv'
24
26
 
25
- def convert
26
- buffer = ""
27
- CSV.generate(buffer) do |csv|
28
- doc = ::Nokogiri::HTML(open("http://www.debian.or.jp/community/translate/trans_table.html", "r"))
29
- doc.css('dl').each do |dl|
30
- dl.children.each_slice(3) do |dt, dd, _|
31
- csv << [dt.text, dd.text.gsub(/(^\/|\/$)/,'')]
32
- end
27
+ private
28
+ def convert_to_csv(csv)
29
+ doc = ::Nokogiri::HTML(open("http://www.debian.or.jp/community/translate/trans_table.html", "r"))
30
+ doc.css('dl').each do |dl|
31
+ dl.children.each_slice(3) do |dt, dd, _|
32
+ csv << [dt.text, dd.text.gsub(/(^\/|\/$)/,'')]
33
33
  end
34
34
  end
35
35
  end
@@ -0,0 +1,50 @@
1
+ # Copyright (C) 2012 Koji SHIMADA <koji.shimada@enishi-tech.com>
2
+ #
3
+ # This program is free software: you can redistribute it and/or modify
4
+ # it under the terms of the GNU General Public License as published by
5
+ # the Free Software Foundation, either version 3 of the License, or
6
+ # (at your option) any later version.
7
+ #
8
+ # This program is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ # GNU General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU General Public License
14
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
15
+
16
+ require 'open-uri'
17
+ require 'zlib'
18
+ require 'stringio'
19
+
20
+ module Logaling
21
+ class Edict < ExternalGlossary
22
+ description 'The EDICT Dictionary File (http://www.csse.monash.edu.au/~jwb/edict.html)'
23
+ source_language 'ja'
24
+ target_language 'en'
25
+ output_format 'csv'
26
+
27
+ private
28
+ def convert_to_csv(csv)
29
+ puts "downloading edict file..."
30
+ url = 'http://ftp.monash.edu.au/pub/nihongo/edict.gz'
31
+ Zlib::GzipReader.open(open(url)) do |gz|
32
+ puts "importing edict file..."
33
+
34
+ lines = StringIO.new(gz.read).each_line
35
+
36
+ lines.next # skip header
37
+
38
+ preprocessed_lines = lines.map do |line|
39
+ line.encode("UTF-8", "EUC-JP").chomp
40
+ end
41
+
42
+ preprocessed_lines.each do |line|
43
+ source, target = line.split('/', 2)
44
+ source = source.strip
45
+ csv << [source, target]
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,60 @@
1
+ # Copyright (C) 2012 Koji SHIMADA
2
+ # Copyright (C) 2012 Kouhei Sutou <kou@clear-code.com>
3
+ #
4
+ # This program is free software: you can redistribute it and/or modify
5
+ # it under the terms of the GNU General Public License as published by
6
+ # the Free Software Foundation, either version 3 of the License, or
7
+ # (at your option) any later version.
8
+ #
9
+ # This program is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU General Public License
15
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
16
+
17
+ require 'open-uri'
18
+ require 'zlib'
19
+ require 'stringio'
20
+ require 'rubygems/package'
21
+
22
+ module Logaling
23
+ class Gene95 < ExternalGlossary
24
+ description 'GENE95 Dictionary (http://www.namazu.org/~tsuchiya/sdic/data/gene.html)'
25
+ source_language 'en'
26
+ target_language 'ja'
27
+ output_format 'csv'
28
+
29
+ private
30
+ def convert_to_csv(csv)
31
+ puts "downloading gene95 dictionary..."
32
+ url = 'http://www.namazu.org/~tsuchiya/sdic/data/gene95.tar.gz'
33
+ Zlib::GzipReader.open(open(url)) do |gz|
34
+ puts "importing gene95 dictionary..."
35
+
36
+ Gem::Package::TarReader.new(gz) do |tar|
37
+ tar.each do |entry|
38
+ case entry.full_name
39
+ when "gene.txt"
40
+ lines = StringIO.new(entry.read).each_line
41
+
42
+ 2.times { lines.next } # skip header
43
+
44
+ preprocessed_lines = lines.map.map do |line|
45
+ line.encode("UTF-8", "CP932",
46
+ undef: :replace, replace: '').chomp
47
+ end
48
+
49
+ preprocessed_lines.each_slice(2) do |source, target|
50
+ csv << [source.sub(/( .*)/, ''), target]
51
+ end
52
+ else
53
+ # ignore
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
@@ -1,4 +1,5 @@
1
1
  # Copyright (C) 2011 Miho SUZUKI
2
+ # Copyright (C) 2012 Kouhei Sutou <kou@clear-code.com>
2
3
  #
3
4
  # This program is free software: you can redistribute it and/or modify
4
5
  # it under the terms of the GNU General Public License as published by
@@ -21,14 +22,13 @@ module Logaling
21
22
  description 'GNOME Translation Project Ja (http://live.gnome.org/TranslationProjectJa)'
22
23
  source_language 'en'
23
24
  target_language 'ja'
25
+ output_format 'csv'
24
26
 
25
- def convert
26
- buffer = ""
27
- CSV.generate(buffer) do |csv|
28
- doc = ::Nokogiri::HTML(open("http://www.gnome.gr.jp/l10n/trans-terms.html", "r"))
29
- doc.css('table tr')[1..-1].each do |tr|
30
- csv << [tr.children[0].text, tr.children[1].text]
31
- end
27
+ private
28
+ def convert_to_csv(csv)
29
+ doc = ::Nokogiri::HTML(open("http://www.gnome.gr.jp/l10n/trans-terms.html", "r"))
30
+ doc.css('table tr')[1..-1].each do |tr|
31
+ csv << [tr.children[0].text, tr.children[1].text]
32
32
  end
33
33
  end
34
34
  end
@@ -1,4 +1,5 @@
1
1
  # Copyright (C) 2011 Miho SUZUKI
2
+ # Copyright (C) 2012 Kouhei Sutou <kou@clear-code.com>
2
3
  #
3
4
  # This program is free software: you can redistribute it and/or modify
4
5
  # it under the terms of the GNU General Public License as published by
@@ -21,15 +22,14 @@ module Logaling
21
22
  description 'PostgreSQL7.1 Manual (http://osb.sraoss.co.jp/PostgreSQL/Manual/)'
22
23
  source_language 'en'
23
24
  target_language 'ja'
25
+ output_format 'csv'
24
26
 
25
- def convert
26
- buffer = ""
27
- CSV.generate(buffer) do |csv|
28
- doc = ::Nokogiri::HTML(open("http://osb.sraoss.co.jp/PostgreSQL/Manual/word.html", "r:iso-2022-jp").read.encode("utf-8"))
29
- doc.css('table table tr')[2..-1].each do |tr|
30
- if tr.children[2]
31
- csv << [tr.children[2].text, tr.children[4].text]
32
- end
27
+ private
28
+ def convert_to_csv(csv)
29
+ doc = ::Nokogiri::HTML(open("http://osb.sraoss.co.jp/PostgreSQL/Manual/word.html", "r:iso-2022-jp").read.encode("utf-8"))
30
+ doc.css('table table tr')[2..-1].each do |tr|
31
+ if tr.children[2]
32
+ csv << [tr.children[2].text, tr.children[4].text]
33
33
  end
34
34
  end
35
35
  end
@@ -42,7 +42,7 @@ class Logaling::ExternalGlossary
42
42
  end
43
43
 
44
44
  def name
45
- self.inspect.underscore.gsub(/.*\//,'')
45
+ self.to_s.underscore.gsub(/.*\//,'')
46
46
  end
47
47
 
48
48
  def description val=nil
@@ -56,14 +56,32 @@ class Logaling::ExternalGlossary
56
56
  def target_language val=nil
57
57
  @target_language ||= val
58
58
  end
59
+
60
+ def output_format(*args)
61
+ if args.empty?
62
+ @output_format ||= "csv"
63
+ else
64
+ @output_format = args.first
65
+ end
66
+ end
59
67
  end
60
68
 
61
69
  def import
62
- File.open(import_file_name, "w") {|f| f.write(self.convert) }
70
+ File.open(import_file_name, "w") do |output|
71
+ output_format = self.class.output_format
72
+ output_format = output_format.to_s if output_format.is_a?(Symbol)
73
+ case output_format
74
+ when "csv"
75
+ convert_to_csv(CSV.new(output))
76
+ else
77
+ raise UnsupportedFormat, "unsupported format: <#{output_format}>"
78
+ end
79
+ end
63
80
  end
64
81
 
65
82
  private
66
83
  def import_file_name
67
- [self.class.name, self.class.source_language, self.class.target_language, 'csv'].join('.')
84
+ [self.class.name, self.class.source_language,
85
+ self.class.target_language, self.class.output_format].join('.')
68
86
  end
69
87
  end
@@ -17,6 +17,7 @@
17
17
 
18
18
  require 'psych'
19
19
  require "yaml"
20
+ require "csv"
20
21
  require "fileutils"
21
22
 
22
23
  module Logaling
@@ -72,10 +73,6 @@ module Logaling
72
73
  FileUtils.touch(@path) unless File.exist?(@path)
73
74
 
74
75
  glossary = Glossary.load_glossary(@path)
75
- if bilingual_pair_exists?(glossary, source_term, target_term)
76
- raise TermError, "term '#{source_term}: #{target_term}' already exists in '#{@glossary}'"
77
- end
78
-
79
76
  glossary << build_term(source_term, target_term, note)
80
77
  dump_glossary(glossary)
81
78
  end
@@ -84,9 +81,6 @@ module Logaling
84
81
  raise GlossaryNotFound unless File.exist?(@path)
85
82
 
86
83
  glossary = Glossary.load_glossary(@path)
87
- if bilingual_pair_exists?(glossary, source_term, new_target_term)
88
- raise TermError, "term '#{source_term}: #{target_term}' already exists in '#{@glossary}'"
89
- end
90
84
 
91
85
  target_index = find_term_index(glossary, source_term, target_term)
92
86
  if target_index
@@ -136,7 +130,9 @@ module Logaling
136
130
  end
137
131
 
138
132
  def rebuild_term(current, source_term, target_term, note)
139
- note = current['note'] if note.nil? || note == ""
133
+ if current['target_term'] != target_term && (note.nil? || note == "")
134
+ note = current['note']
135
+ end
140
136
  target_term = current['target_term'] if target_term == ""
141
137
  build_term(source_term, target_term, note)
142
138
  end
@@ -151,10 +147,6 @@ module Logaling
151
147
  end
152
148
  end
153
149
 
154
- def bilingual_pair_exists?(glossary, source_term, target_term)
155
- target_terms(glossary, source_term).any?{|data| data['target_term'] == target_term }
156
- end
157
-
158
150
  def target_terms(glossary, source_term)
159
151
  glossary.select {|term| term['source_term'] == source_term }
160
152
  end
@@ -15,14 +15,13 @@
15
15
  # You should have received a copy of the GNU General Public License
16
16
  # along with this program. If not, see <http://www.gnu.org/licenses/>.
17
17
 
18
- require 'psych'
19
- require "yaml"
20
- require "fileutils"
21
18
  require 'groonga'
22
- require 'csv'
19
+ require 'cgi'
23
20
 
24
21
  module Logaling
25
22
  class GlossaryDB
23
+ VERSION = 1
24
+
26
25
  def self.open(base_path, encoding, &blk)
27
26
  blk ? GlossaryDB.new.open(base_path, encoding, &blk) : GlossaryDB.new.open(base_path, encoding)
28
27
  end
@@ -50,8 +49,12 @@ module Logaling
50
49
  end
51
50
 
52
51
  def recreate_table
53
- remove_schema
54
- populate_schema
52
+ version = Groonga["configurations"] ? get_config("version") : 0
53
+ if version.to_i != VERSION
54
+ remove_schema
55
+ populate_schema
56
+ add_config("version", VERSION.to_s)
57
+ end
55
58
  end
56
59
 
57
60
  def close
@@ -59,27 +62,80 @@ module Logaling
59
62
  @database = nil
60
63
  end
61
64
 
62
- def index_glossary(glossary, name, source_language, target_language)
65
+ def deindex_glossary(glossary_name, glossary_source)
66
+ delete_translations_by_glossary_source(glossary_source)
67
+ delete_glossary(glossary_name)
68
+ delete_glossary_source(glossary_source)
69
+ end
70
+
71
+ def index_glossary(glossary, glossary_name, glossary_source, source_language, target_language, indexed_at)
72
+ deindex_glossary(glossary_name, glossary_source)
73
+
74
+ add_glossary_source(glossary_source, indexed_at)
75
+ add_glossary(glossary_name)
63
76
  glossary.each do |term|
64
77
  source_term = term['source_term']
65
78
  target_term = term['target_term']
66
79
  note = term['note']
67
- add_glossary(name, source_language, target_language, source_term, target_term, note)
80
+ add_translation(glossary_name, glossary_source, source_language, target_language, source_term, target_term, note)
68
81
  end
69
82
  end
70
83
 
71
- def lookup(source_term)
72
- records_raw = Groonga["glossaries"].select do |record|
73
- record.source_term =~ source_term
84
+ def lookup(source_term, source_language, target_language, glossary)
85
+ records_selected = Groonga["translations"].select do |record|
86
+ conditions = [record.source_term =~ source_term]
87
+ conditions << (record.source_language =~ source_language) if source_language
88
+ conditions << (record.target_language =~ target_language) if target_language
89
+ conditions
90
+ end
91
+ specified_glossary = records_selected.select do |record|
92
+ record.glossary == glossary
74
93
  end
94
+ specified_glossary.each do |record|
95
+ record.key._score += 10
96
+ end
97
+ records = records_selected.sort([
98
+ {:key=>"_score", :order=>'descending'},
99
+ {:key=>"glossary", :order=>'ascending'},
100
+ {:key=>"source_term", :order=>'ascending'},
101
+ {:key=>"target_term", :order=>'ascending'}])
102
+
103
+ options = {:width => 100,
104
+ :html_escape => true,
105
+ :normalize => true}
106
+ snippet = records_selected.expression.snippet(["<snippet>", "</snippet>"], options)
107
+
108
+ snipped_source_term = []
109
+ records.map do |record|
110
+ term = record.key
111
+ snipped_text = snippet.execute(term.source_term).join
112
+ {:glossary_name => term.glossary.key,
113
+ :source_language => term.source_language,
114
+ :target_language => term.target_language,
115
+ :source_term => term.source_term,
116
+ :snipped_source_term => struct_snipped_text(snipped_text),
117
+ :target_term => term.target_term,
118
+ :note => term.note || ''}
119
+ end
120
+ end
121
+
122
+ def translation_list(glossary, source_language, target_language)
123
+ records_raw = Groonga["translations"].select do |record|
124
+ [
125
+ record.glossary == glossary,
126
+ record.source_language == source_language,
127
+ record.target_language == target_language
128
+ ]
129
+ end
130
+
75
131
  records = records_raw.sort([
76
- {:key=>"name", :order=>'ascending'},
77
132
  {:key=>"source_term", :order=>'ascending'},
78
133
  {:key=>"target_term", :order=>'ascending'}])
79
134
 
80
135
  records.map do |record|
81
136
  term = record.key
82
- {:name => term.name,
137
+
138
+ {:glossary_name => term.glossary.key,
83
139
  :source_language => term.source_language,
84
140
  :target_language => term.target_language,
85
141
  :source_term => term.source_term,
@@ -88,15 +144,119 @@ module Logaling
88
144
  end
89
145
  end
90
146
 
147
+ def get_bilingual_pair(source_term, target_term, glossary)
148
+ records = Groonga["translations"].select do |record|
149
+ [
150
+ record.glossary == glossary,
151
+ record.source_term == source_term,
152
+ record.target_term == target_term
153
+ ]
154
+ end
155
+
156
+ records.map do |record|
157
+ term = record.key
158
+
159
+ {:glossary_name => term.glossary,
160
+ :source_language => term.source_language,
161
+ :target_language => term.target_language,
162
+ :source_term => term.source_term,
163
+ :target_term => term.target_term,
164
+ :note => term.note || ''}
165
+ end
166
+ end
167
+
168
+ def get_bilingual_pair_with_note(source_term, target_term, note, glossary)
169
+ records = Groonga["translations"].select do |record|
170
+ [
171
+ record.glossary == glossary,
172
+ record.source_term == source_term,
173
+ record.target_term == target_term,
174
+ record.note == note
175
+ ]
176
+ end
177
+
178
+ records.map do |record|
179
+ term = record.key
180
+
181
+ {:glossary_name => term.glossary,
182
+ :source_language => term.source_language,
183
+ :target_language => term.target_language,
184
+ :source_term => term.source_term,
185
+ :target_term => term.target_term,
186
+ :note => term.note || ''}
187
+ end
188
+ end
189
+
190
+ def glossary_source_exist?(glossary_source, indexed_at)
191
+ glossary = Groonga["glossary_sources"].select do |record|
192
+ [
193
+ record.key == glossary_source,
194
+ record.indexed_at == indexed_at
195
+ ]
196
+ end
197
+ !glossary.size.zero?
198
+ end
199
+
200
+ def get_all_glossary_source
201
+ Groonga["glossary_sources"].sort([
202
+ {:key=>"_key", :order=>'ascending'}
203
+ ]).map{|record| record.key}
204
+ end
205
+
206
+ def get_all_glossary
207
+ Groonga["glossaries"].sort([
208
+ {:key=>"_key", :order=>'ascending'}
209
+ ]).map{|record| record.key}
210
+ end
211
+
91
212
  private
92
- def add_glossary(name, source_language, target_language, source_term, target_term, note)
93
- Groonga["glossaries"].add(:name => name,
94
- :source_language => source_language,
95
- :target_language => target_language,
96
- :source_term => source_term,
97
- :target_term => target_term,
98
- :note => note,
99
- )
213
+ def delete_glossary_source(glossary_source)
214
+ records = Groonga["glossary_sources"].select do |record|
215
+ record.key == glossary_source
216
+ end
217
+
218
+ records.each do |record|
219
+ record.key.delete
220
+ end
221
+ end
222
+
223
+ def add_glossary_source(glossary_source, indexed_at)
224
+ Groonga["glossary_sources"].add(glossary_source, :indexed_at => indexed_at)
225
+ end
226
+
227
+ def delete_glossary(glossary_name)
228
+ records = Groonga["glossaries"].select do |record|
229
+ record.key == glossary_name
230
+ end
231
+
232
+ records.each do |record|
233
+ record.key.delete
234
+ end
235
+ end
236
+
237
+ def add_glossary(glossary_name)
238
+ Groonga["glossaries"].add(glossary_name)
239
+ end
240
+
241
+ def delete_translations_by_glossary_source(glossary_source)
242
+ records = Groonga["translations"].select do |record|
243
+ record.glossary_source == glossary_source
244
+ end
245
+
246
+ records.each do |record|
247
+ record.key.delete
248
+ end
249
+ end
250
+
251
+ def add_translation(glossary_name, glossary_source, source_language, target_language, source_term, target_term, note)
252
+ Groonga["translations"].add(:glossary => glossary_name,
253
+ :glossary_source => glossary_source,
254
+ :source_language => source_language,
255
+ :target_language => target_language,
256
+ :source_term => source_term,
257
+ :target_term => target_term,
258
+ :note => note,
259
+ )
100
260
  end
101
261
 
102
262
  def reset_context(encoding)
@@ -110,8 +270,25 @@ module Logaling
110
270
 
111
271
  def populate_schema
112
272
  Groonga::Schema.define do |schema|
113
- schema.create_table("glossaries") do |table|
114
- table.short_text("name")
273
+ schema.create_table("configurations") do |table|
274
+ table.short_text("conf_key")
275
+ table.text("conf_value")
276
+ end
277
+
278
+ schema.create_table("glossary_sources",
279
+ :type => :hash,
280
+ :key_type => "ShortText") do |table|
281
+ table.time("indexed_at")
282
+ end
283
+
284
+ schema.create_table("glossaries",
285
+ :type => :hash,
286
+ :key_type => "ShortText") do |table|
287
+ end
288
+
289
+ schema.create_table("translations") do |table|
290
+ table.reference("glossary", "glossaries")
291
+ table.reference("glossary_source", "glossary_sources")
115
292
  table.short_text("source_language")
116
293
  table.short_text("target_language")
117
294
  table.short_text("source_term")
@@ -124,14 +301,17 @@ module Logaling
124
301
  :key_type => "ShortText",
125
302
  :key_normalize => true,
126
303
  :default_tokenizer => "TokenBigram") do |table|
127
- table.index("glossaries.source_term")
304
+ table.index("translations.source_term")
128
305
  end
129
306
  end
130
307
  end
131
308
 
132
309
  def remove_schema
133
310
  Groonga::Schema.define do |schema|
311
+ schema.remove_table("configurations") if Groonga["configurations"]
312
+ schema.remove_table("translations") if Groonga["translations"]
134
313
  schema.remove_table("glossaries") if Groonga["glossaries"]
314
+ schema.remove_table("glossary_sources") if Groonga["glossary_sources"]
135
315
  schema.remove_table("terms") if Groonga["terms"]
136
316
  end
137
317
  end
@@ -139,5 +319,33 @@ module Logaling
139
319
  def closed?
140
320
  @database.nil? or @database.closed?
141
321
  end
322
+
323
+ def struct_snipped_text(snipped_text)
324
+ word_list = snipped_text.split(/(<snippet>[^<]*<\/snippet>)/)
325
+ structed_source_term = word_list.map{|word|
326
+ replaced_word = word.sub(/<snippet>([^<]*)<\/snippet>/){|match| $1}
327
+ if replaced_word == word
328
+ CGI.unescapeHTML(word)
329
+ else
330
+ {:keyword => CGI.unescapeHTML(replaced_word)}
331
+ end
332
+ }
333
+ structed_source_term
334
+ end
335
+
336
+ def get_config(conf_key)
337
+ records = Groonga["configurations"].select do |record|
338
+ record.conf_key == conf_key
339
+ end
340
+ value = records.map do |record|
341
+ config = record.key
342
+ config.conf_value
343
+ end
344
+ value.size > 0 ? value[0] : ""
345
+ end
346
+
347
+ def add_config(conf_key, conf_value)
348
+ Groonga["configurations"].add(:conf_key => conf_key, :conf_value => conf_value)
349
+ end
142
350
  end
143
351
  end
@@ -55,36 +55,54 @@ module Logaling
55
55
 
56
56
  terms = []
57
57
  Logaling::GlossaryDB.open(logaling_db_home, "utf8") do |db|
58
- terms = db.lookup(source_term)
59
- terms.delete_if{|term| term[:source_language] != source_language } if source_language
60
- terms.delete_if{|term| term[:target_language] != target_language } if target_language
61
- if glossary && !terms.empty?
62
- # order by glossary
63
- specified = terms.select{|term| term[:name] == glossary}
64
- other = terms.select{|term| term[:name] != glossary}
65
- terms = specified.concat(other)
66
- end
58
+ terms = db.lookup(source_term, source_language, target_language, glossary)
59
+ end
60
+ terms
61
+ end
62
+
63
+ def show_glossary(glossary, source_language, target_language)
64
+ raise GlossaryDBNotFound unless File.exist?(logaling_db_home)
65
+
66
+ terms = []
67
+ Logaling::GlossaryDB.open(logaling_db_home, "utf8") do |db|
68
+ terms = db.translation_list(glossary, source_language, target_language)
67
69
  end
68
70
  terms
69
71
  end
70
72
 
73
+ def list
74
+ raise GlossaryDBNotFound unless File.exist?(logaling_db_home)
75
+
76
+ glossaries = []
77
+ Logaling::GlossaryDB.open(logaling_db_home, "utf8") do |db|
78
+ glossaries = db.get_all_glossary
79
+ end
80
+ glossaries
81
+ end
82
+
71
83
  def index
72
- return if latest_index?
73
- projects = Dir[File.join(@path, "projects", "*")]
84
+ project_glossaries = Dir[File.join(@path, "projects", "*")].map do |project|
85
+ Dir.glob(get_all_glossary_sources(File.join(project, "glossary")))
86
+ end
87
+ imported_glossaries = Dir.glob(get_all_glossary_sources(cache_path))
88
+ all_glossaries = project_glossaries.flatten + imported_glossaries
74
89
 
75
90
  Logaling::GlossaryDB.open(logaling_db_home, "utf8") do |db|
76
91
  db.recreate_table
77
- projects.each do |project|
78
- get_glossaries_from_project(project).each do |glossary, name, source_language, target_language|
79
- db.index_glossary(glossary, name, source_language, target_language)
92
+ all_glossaries.each do |glossary_source|
93
+ indexed_at = File.mtime(glossary_source)
94
+ unless db.glossary_source_exist?(glossary_source, indexed_at)
95
+ glossary_name, source_language, target_language = get_glossary(glossary_source)
96
+ puts "now index #{glossary_name}..."
97
+ db.index_glossary(Glossary.load(glossary_source), glossary_name, glossary_source, source_language, target_language, indexed_at)
80
98
  end
81
99
  end
82
- get_glossaries(cache_path).each do |glossary, name, source_language, target_language|
83
- db.index_glossary(glossary, name, source_language, target_language)
100
+ (db.get_all_glossary_source - all_glossaries).each do |glossary_source|
101
+ glossary_name, source_language, target_language = get_glossary(glossary_source)
102
+ puts "now deindex #{glossary_name}..."
103
+ db.deindex_glossary(glossary_name, glossary_source)
84
104
  end
85
105
  end
86
-
87
- FileUtils.touch(index_at_file)
88
106
  end
89
107
 
90
108
  def glossary_counts
@@ -96,33 +114,43 @@ module Logaling
96
114
  File.exist?(path) ? path : nil
97
115
  end
98
116
 
99
- private
100
- def latest_index?
101
- if File.exist?(index_at_file)
102
- index_at = File.mtime(index_at_file)
103
- all_glossary_files = [cache_path, registered_projects.map{|path| File.join(path, "glossary")}].flatten.map{|path| get_all_glossary_paths(path)}.flatten
104
- unless Dir.glob(all_glossary_files).any?{|file| File.mtime(file) >= index_at }
105
- true
106
- else
107
- false
108
- end
117
+ def bilingual_pair_exists?(source_term, target_term, glossary)
118
+ raise GlossaryDBNotFound unless File.exist?(logaling_db_home)
119
+
120
+ terms = []
121
+ Logaling::GlossaryDB.open(logaling_db_home, "utf8") do |db|
122
+ terms = db.get_bilingual_pair(source_term, target_term, glossary)
123
+ end
124
+
125
+ if terms.size > 0
126
+ true
109
127
  else
110
128
  false
111
129
  end
112
130
  end
113
131
 
114
- def get_glossaries(path)
115
- Dir.glob(get_all_glossary_paths(path)).map do |file|
116
- name, source_language, target_language = File::basename(file, ".*").split(".")
117
- [Glossary.load(file), name, source_language, target_language]
132
+ def bilingual_pair_exists_and_has_same_note?(source_term, target_term, note, glossary)
133
+ raise GlossaryDBNotFound unless File.exist?(logaling_db_home)
134
+
135
+ terms = []
136
+ Logaling::GlossaryDB.open(logaling_db_home, "utf8") do |db|
137
+ terms = db.get_bilingual_pair_with_note(source_term, target_term, note, glossary)
138
+ end
139
+
140
+ if terms.size > 0
141
+ true
142
+ else
143
+ false
118
144
  end
119
145
  end
120
146
 
121
- def get_glossaries_from_project(path)
122
- get_glossaries(File.join(path, "glossary"))
147
+ private
148
+ def get_glossary(path)
149
+ glossary_name, source_language, target_language = File::basename(path, ".*").split(".")
150
+ [glossary_name, source_language, target_language]
123
151
  end
124
152
 
125
- def get_all_glossary_paths(path)
153
+ def get_all_glossary_sources(path)
126
154
  %w(yml tsv csv).map{|type| File.join(path, "*.#{type}") }
127
155
  end
128
156
 
@@ -145,9 +173,5 @@ module Logaling
145
173
  def imported_glossaries
146
174
  Dir[File.join(cache_path, "*")]
147
175
  end
148
-
149
- def index_at_file
150
- File.join(logaling_db_home, "index_at")
151
- end
152
176
  end
153
177
  end
data/lib/logaling.rb CHANGED
@@ -1,6 +1,7 @@
1
- # -*- encoding: utf-8 -*-
1
+ # -*- coding: utf-8 -*-
2
2
  #
3
3
  # Copyright (C) 2011 Miho SUZUKI
4
+ # Copyright (C) 2011 Kouhei Sutou <kou@clear-code.com>
4
5
  #
5
6
  # This program is free software: you can redistribute it and/or modify
6
7
  # it under the terms of the GNU General Public License as published by
@@ -25,4 +26,5 @@ module Logaling
25
26
  class GlossaryNotFound < LogalingError; end
26
27
  class GlossaryDBNotFound < LogalingError; end
27
28
  class ExternalGlossaryNotFound < LogalingError; end
29
+ class UnsupportedFormat < LogalingError; end
28
30
  end
@@ -22,6 +22,7 @@ describe Logaling::Command do
22
22
  let(:command) { Logaling::Command.new([], base_options) }
23
23
  let(:glossary_path) { Logaling::Glossary.build_path('spec', 'en', 'ja') }
24
24
  let(:target_project_path) { File.join(LOGALING_HOME, "projects", "spec") }
25
+ let(:repository) { Logaling::Repository.new(LOGALING_HOME) }
25
26
 
26
27
  before do
27
28
  FileUtils.remove_entry_secure(Logaling::Command::LOGALING_CONFIG, true)
@@ -80,6 +81,7 @@ describe Logaling::Command do
80
81
 
81
82
  describe '#register' do
82
83
  before do
84
+ sleep(1)
83
85
  @project_counts = Dir[File.join(LOGALING_HOME, "projects", "*")].size
84
86
  end
85
87
 
@@ -293,35 +295,40 @@ describe Logaling::Command do
293
295
 
294
296
  describe "#update" do
295
297
  before do
298
+ FileUtils.remove_entry_secure(File.join(LOGALING_HOME, "db", "index_at"), true)
296
299
  command.new('spec', 'en', 'ja')
297
300
  command.add("spec", "テスト", "備考")
298
301
  end
299
302
 
300
- context "not given source-term option" do
301
- # should show err
302
- end
303
-
304
- context "not given target-term option" do
305
- #should show err
306
- end
303
+ context "with arguments except note" do
304
+ before do
305
+ command.update("spec", "テスト", "スペック")
306
+ @yaml = YAML::load_file(glossary_path).find{|h| h["source_term"] == "spec" }
307
+ end
307
308
 
308
- context "not given new-target-term option" do
309
- #should show err
309
+ it "term's target_term should be updated" do
310
+ @yaml.should == {"source_term"=>"spec", "target_term"=>"スペック", "note"=>"備考"}
311
+ end
310
312
  end
311
313
 
312
- context "with arguments except note" do
314
+ context 'with exisiting bilingual pair and note' do
313
315
  before do
314
- command.update("spec", "テスト", "スペック")
316
+ @stdout = capture(:stdout) { command.update("spec", "テスト", "テスト", "備考") }
315
317
  end
316
318
 
317
- subject { YAML::load_file(glossary_path).find{|h| h["source_term"] == "spec" }}
319
+ it 'should show error message' do
320
+ @stdout.should include "already exists"
321
+ end
322
+ end
318
323
 
319
- it "term's target_term should be updated" do
320
- subject["target_term"].should == "スペック"
324
+ context 'with existing bilingual pair and different note' do
325
+ before do
326
+ command.update("spec", "テスト", "テスト", "備考だけ書き換え")
327
+ @yaml = YAML::load_file(glossary_path).find{|h| h["source_term"] == "spec" }
321
328
  end
322
329
 
323
- it "term's note should not be updated" do
324
- subject["note"].should == "備考"
330
+ it "should update note" do
331
+ @yaml.should == {"source_term"=>"spec", "target_term"=>"テスト", "note"=>"備考だけ書き換え"}
325
332
  end
326
333
  end
327
334
  end
@@ -409,6 +416,74 @@ describe Logaling::Command do
409
416
  end
410
417
  end
411
418
 
419
+ describe "#show" do
420
+ let(:csv_path) { File.join(File.dirname(glossary_path), "spec.ja.en.csv") }
421
+ before do
422
+ command.new('spec', 'en', 'ja')
423
+ command.add("spec", "スペック", "備考")
424
+ command.add("spec-test", "スペックてすと", "備考")
425
+ command.add("spec-test-test", "スペックてすとてすと", "備考")
426
+
427
+ FileUtils.mkdir_p(File.dirname(glossary_path))
428
+ FileUtils.touch(csv_path)
429
+ File.open(csv_path, "w"){|f| f.puts "test_logaling,テスト"}
430
+ end
431
+
432
+ context 'when .logaling exists' do
433
+ before do
434
+ @stdout = capture(:stdout) {command.show}
435
+ end
436
+
437
+ it 'should show translation list' do
438
+ @stdout.should include "spec"
439
+ @stdout.should include "spec-test"
440
+ @stdout.should include "spec-test-test"
441
+ @stdout.should_not include "test_logaling"
442
+ end
443
+ end
444
+
445
+ context 'with arguments glossary' do
446
+ before do
447
+ command.options = base_options.merge("glossary" => "spec", "source-language" => "ja", "target-language" => "en")
448
+ @stdout = capture(:stdout) {command.show}
449
+ end
450
+
451
+ it 'should show translation list' do
452
+ @stdout.should include "test_logaling"
453
+ @stdout.should_not include "spec-test-test"
454
+ end
455
+ end
456
+
457
+ after do
458
+ FileUtils.remove_entry_secure(csv_path, true)
459
+ end
460
+ end
461
+
462
+ describe '#list' do
463
+ context 'when some glossaries are registered' do
464
+ before do
465
+ command.new('spec', 'en', 'ja')
466
+ @stdout = capture(:stdout) {command.list}
467
+ end
468
+
469
+ it 'should list glossaries' do
470
+ @stdout.should include "spec"
471
+ end
472
+ end
473
+
474
+ context 'when a glossary is unregistered' do
475
+ before do
476
+ command.new('spec', 'en', 'ja')
477
+ repository.unregister('spec')
478
+ @stdout = capture(:stdout) {command.list}
479
+ end
480
+
481
+ it 'should not include unregistered glossary' do
482
+ @stdout.should_not include "spec"
483
+ end
484
+ end
485
+ end
486
+
412
487
  after do
413
488
  FileUtils.remove_entry_secure(Logaling::Command::LOGALING_CONFIG, true)
414
489
  FileUtils.remove_entry_secure(File.join(LOGALING_HOME, 'projects', 'spec'), true)
@@ -43,16 +43,6 @@ module Logaling
43
43
  end
44
44
  end
45
45
 
46
- context 'with arguments show existing bilingual pair' do
47
- before do
48
- glossary.add("user", "ユーザ", "ユーザーではない")
49
- end
50
-
51
- it {
52
- -> { glossary.add("user", "ユーザ", "ユーザーではない") }.should raise_error(Logaling::TermError)
53
- }
54
- end
55
-
56
46
  context "when the glossary not found" do
57
47
  before do
58
48
  glossary.add("test", "テスト", "テスト")
@@ -77,17 +67,30 @@ module Logaling
77
67
  }
78
68
  end
79
69
 
80
- context 'with source-term arguments show not existing bilingual pair' do
70
+ context 'with source-term show not existing bilingual pair' do
81
71
  it {
82
72
  -> { glossary.update("use", "ユーザ", "ユーザー", "やっぱりユーザー") }.should raise_error(Logaling::TermError)
83
73
  }
84
74
  end
85
75
 
86
- context 'with target-term arguments show not existing bilingual pair' do
76
+ context 'with target-term show not existing bilingual pair' do
87
77
  it {
88
78
  -> { glossary.update("user", "ユー", "ユーザー", "やっぱりユーザー") }.should raise_error(Logaling::TermError)
89
79
  }
90
80
  end
81
+
82
+ context 'with same target-term and empty note' do
83
+ before do
84
+ glossary.update("user", "ユーザ", "ユーザ", "")
85
+ end
86
+
87
+ it 'should clear note' do
88
+ yaml = YAML::load_file(glossary_path)
89
+ term = yaml.index({"source_term"=>"user", "target_term"=>"ユーザ", "note"=>""})
90
+ term.should_not be_nil
91
+ end
92
+
93
+ end
91
94
  end
92
95
 
93
96
  describe '#delete' do
@@ -101,8 +104,8 @@ module Logaling
101
104
  end
102
105
 
103
106
  it 'should delete the bilingual pair' do
104
- @result.should include({:name=>"spec", :source_language=>"en", :target_language=>"ja", :source_term=>"delete_logaling", :target_term=>"てすと2", :note=>"備考"})
105
- @result.should_not include({:name=>"spec", :source_language=>"en", :target_language=>"ja", :source_term=>"delete_logaling", :target_term=>"てすと1", :note=>"備考"})
107
+ @result.any?{|term| term[:source_term] == "delete_logaling" && term[:target_term] == "てすと2"}.should be_true
108
+ @result.any?{|term| term[:source_term] == "delete_logaling" && term[:target_term] == "てすと1"}.should be_false
106
109
  end
107
110
  end
108
111
 
@@ -138,7 +141,7 @@ module Logaling
138
141
  end
139
142
 
140
143
  it 'should delete the term' do
141
- @result.should_not include({:name=>"spec", :source_language=>"en", :target_language=>"ja", :source_term=>"user_logaling", :target_term=>"ユーザ", :note=>"備考"})
144
+ @result.any?{|term| term[:source_term] == "user_logaling" && term[:target_term] == "ユーザ"}.should be_false
142
145
  end
143
146
  end
144
147
 
@@ -158,8 +161,8 @@ module Logaling
158
161
  }
159
162
 
160
163
  it "should delete terms when force option is true" do
161
- @result.should_not include({:name=>"spec", :source_language=>"en", :target_language=>"ja", :source_term=>"delete_loglaing", :target_term=>"てすと1", :note=>"備考"})
162
- @result.should_not include({:name=>"spec", :source_language=>"en", :target_language=>"ja", :source_term=>"delete_logaling", :target_term=>"てすと2", :note=>"備考"})
164
+ @result.any?{|term| term[:source_term] == "delete_logaling" && term[:target_term] == "てすと1"}.should be_false
165
+ @result.any?{|term| term[:source_term] == "delete_logaling" && term[:target_term] == "てすと2"}.should be_false
163
166
  end
164
167
  end
165
168
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: logaling-command
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -13,11 +13,11 @@ authors:
13
13
  autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
- date: 2011-12-20 00:00:00.000000000Z
16
+ date: 2012-01-30 00:00:00.000000000Z
17
17
  dependencies:
18
18
  - !ruby/object:Gem::Dependency
19
19
  name: thor
20
- requirement: &2158772960 !ruby/object:Gem::Requirement
20
+ requirement: &2153162840 !ruby/object:Gem::Requirement
21
21
  none: false
22
22
  requirements:
23
23
  - - ! '>='
@@ -25,10 +25,10 @@ dependencies:
25
25
  version: 0.14.6
26
26
  type: :runtime
27
27
  prerelease: false
28
- version_requirements: *2158772960
28
+ version_requirements: *2153162840
29
29
  - !ruby/object:Gem::Dependency
30
30
  name: bundler
31
- requirement: &2158771780 !ruby/object:Gem::Requirement
31
+ requirement: &2153162000 !ruby/object:Gem::Requirement
32
32
  none: false
33
33
  requirements:
34
34
  - - ! '>='
@@ -36,10 +36,10 @@ dependencies:
36
36
  version: '1.0'
37
37
  type: :runtime
38
38
  prerelease: false
39
- version_requirements: *2158771780
39
+ version_requirements: *2153162000
40
40
  - !ruby/object:Gem::Dependency
41
41
  name: rroonga
42
- requirement: &2158770780 !ruby/object:Gem::Requirement
42
+ requirement: &2153155300 !ruby/object:Gem::Requirement
43
43
  none: false
44
44
  requirements:
45
45
  - - ! '>='
@@ -47,10 +47,10 @@ dependencies:
47
47
  version: 1.3.0
48
48
  type: :runtime
49
49
  prerelease: false
50
- version_requirements: *2158770780
50
+ version_requirements: *2153155300
51
51
  - !ruby/object:Gem::Dependency
52
52
  name: rainbow
53
- requirement: &2158769700 !ruby/object:Gem::Requirement
53
+ requirement: &2153154740 !ruby/object:Gem::Requirement
54
54
  none: false
55
55
  requirements:
56
56
  - - ! '>='
@@ -58,10 +58,10 @@ dependencies:
58
58
  version: '0'
59
59
  type: :runtime
60
60
  prerelease: false
61
- version_requirements: *2158769700
61
+ version_requirements: *2153154740
62
62
  - !ruby/object:Gem::Dependency
63
63
  name: nokogiri
64
- requirement: &2158768880 !ruby/object:Gem::Requirement
64
+ requirement: &2153153780 !ruby/object:Gem::Requirement
65
65
  none: false
66
66
  requirements:
67
67
  - - ! '>='
@@ -69,10 +69,10 @@ dependencies:
69
69
  version: '0'
70
70
  type: :runtime
71
71
  prerelease: false
72
- version_requirements: *2158768880
72
+ version_requirements: *2153153780
73
73
  - !ruby/object:Gem::Dependency
74
74
  name: active_support
75
- requirement: &2158768160 !ruby/object:Gem::Requirement
75
+ requirement: &2153152800 !ruby/object:Gem::Requirement
76
76
  none: false
77
77
  requirements:
78
78
  - - ! '>='
@@ -80,10 +80,10 @@ dependencies:
80
80
  version: '0'
81
81
  type: :runtime
82
82
  prerelease: false
83
- version_requirements: *2158768160
83
+ version_requirements: *2153152800
84
84
  - !ruby/object:Gem::Dependency
85
85
  name: rake
86
- requirement: &2158767380 !ruby/object:Gem::Requirement
86
+ requirement: &2153151540 !ruby/object:Gem::Requirement
87
87
  none: false
88
88
  requirements:
89
89
  - - ! '>='
@@ -91,10 +91,10 @@ dependencies:
91
91
  version: '0'
92
92
  type: :development
93
93
  prerelease: false
94
- version_requirements: *2158767380
94
+ version_requirements: *2153151540
95
95
  - !ruby/object:Gem::Dependency
96
96
  name: rspec
97
- requirement: &2158766720 !ruby/object:Gem::Requirement
97
+ requirement: &2153150900 !ruby/object:Gem::Requirement
98
98
  none: false
99
99
  requirements:
100
100
  - - ! '>='
@@ -102,7 +102,7 @@ dependencies:
102
102
  version: '0'
103
103
  type: :development
104
104
  prerelease: false
105
- version_requirements: *2158766720
105
+ version_requirements: *2153150900
106
106
  description: A command line interface for logaling.
107
107
  email:
108
108
  - koji.shimada@enishi-tech.com
@@ -117,6 +117,7 @@ extra_rdoc_files: []
117
117
  files:
118
118
  - .gitignore
119
119
  - .rspec
120
+ - CHANGES
120
121
  - COPYING
121
122
  - Gemfile
122
123
  - README.md
@@ -125,6 +126,8 @@ files:
125
126
  - lib/logaling.rb
126
127
  - lib/logaling/command.rb
127
128
  - lib/logaling/external_glossaries/debian_project.rb
129
+ - lib/logaling/external_glossaries/edict.rb
130
+ - lib/logaling/external_glossaries/gene95.rb
128
131
  - lib/logaling/external_glossaries/gnome_project.rb
129
132
  - lib/logaling/external_glossaries/postgresql_manual.rb
130
133
  - lib/logaling/external_glossary.rb