logaling-command 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGES CHANGED
@@ -1,3 +1,21 @@
1
+ = 0.1.3 / 2012-02-29
2
+
3
+ * Mozilla Japan プロジェクトの対訳用語集をインポートできるようにしました。(kdmsnr さん)
4
+
5
+ * FreeBSD jpman プロジェクトの対訳用語集をインポートできるようにしました。
6
+
7
+ * lookup 時にCSV、JSON形式で出力できるように --output オプションを用意しました。
8
+
9
+ * lookup 時に翻訳言語が違う用語集や対訳からも検索出来るように --dictionary オプションを用意しました。
10
+
11
+ * lookup、show、list を pager なしでも実行できるように、--no-pager オプションを用意しました。
12
+
13
+ * lookup の検索結果に色付けをさせない --no-color オプションを用意しました。
14
+
15
+ * .logaling を任意の場所に指定できるように --logaling-config オプションを用意しました。
16
+
17
+ * --logaling-home を指定できなくなっていた不具合を修正しました。
18
+
1
19
  = 0.1.2 / 2012-01-30
2
20
 
3
21
  * 英和 / 和英 辞書のインポートができるようになりました。他プロジェクトの用語集をインポートする `loga import` と同じ手順でインポートすることができます。
data/README.md CHANGED
@@ -5,22 +5,22 @@ You can add/update/delete terms to your glossary, and search glossaries at once.
5
5
 
6
6
  ### To install:
7
7
 
8
- % gem install logaling-command
8
+ % gem install logaling-command
9
9
 
10
10
  ### Usage:
11
11
 
12
12
  Create new glossary:
13
13
 
14
- % loga new my_glossary en ja
14
+ % loga new my_glossary en ja
15
15
 
16
16
  Add term to glossary:
17
17
 
18
- % loga add developer 開発者
18
+ % loga add developer 開発者
19
19
 
20
20
  Lookup glossary:
21
21
 
22
- % loga lookup develop<br/>
23
- developer ソフトウェア開発者 (my_glossary)
22
+ % loga lookup develop
23
+ developer 開発者 (my_glossary)
24
24
 
25
25
  ### License
26
26
 
data/bin/loga CHANGED
@@ -21,5 +21,4 @@ LOGALING_HOME = File.expand_path("~/.logaling.d")
21
21
 
22
22
  require "logaling"
23
23
 
24
- Logaling::Command.start
25
-
24
+ Logaling::Command::Application.start
@@ -0,0 +1,383 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # Copyright (C) 2011 Miho SUZUKI
4
+ #
5
+ # This program is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # This program is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
17
+
18
+ require 'thor'
19
+ require 'rainbow'
20
+ require "logaling/repository"
21
+ require "logaling/glossary"
22
+ require "logaling/config"
23
+
24
+ module Logaling::Command
25
+ LOGALING_CONFIG = '.logaling'
26
+
27
+ class Application < Thor
28
+
29
+ def initialize(*args)
30
+ super
31
+ @logaling_home = options["logaling-home"] ? options["logaling-home"] : LOGALING_HOME
32
+ @repository = Logaling::Repository.new(@logaling_home)
33
+ @config = Logaling::Config.load(@repository.config_path)
34
+
35
+ @dotfile_path = options["logaling-config"] ? options["logaling-config"] : find_dotfile
36
+ @project_config_path = File.join(@dotfile_path, 'config')
37
+ @config.load(@project_config_path)
38
+ rescue Logaling::CommandFailed # can't find .logaling
39
+ @project_config_path = nil
40
+ ensure
41
+ @config.merge!(options)
42
+ end
43
+
44
+ map '-a' => :add,
45
+ '-d' => :delete,
46
+ '-u' => :update,
47
+ '-l' => :lookup,
48
+ '-i' => :import,
49
+ '-n' => :new,
50
+ '-r' => :register,
51
+ '-U' => :unregister,
52
+ '-L' => :list,
53
+ '-s' => :show,
54
+ '-v' => :version
55
+
56
+ class_option "glossary", type: :string, aliases: "-g"
57
+ class_option "source-language", type: :string, aliases: "-S"
58
+ class_option "target-language", type: :string, aliases: "-T"
59
+ class_option "logaling-home", type: :string, aliases: "-h"
60
+ class_option "logaling-config", type: :string, aliases: "-c"
61
+
62
+ desc 'new [PROJECT NAME] [SOURCE LANGUAGE] [TARGET LANGUAGE(optional)]', 'Create .logaling'
63
+ method_option "no-register", type: :boolean, default: false
64
+ def new(project_name, source_language, target_language=nil)
65
+ unless File.exist?(logaling_config_path)
66
+ FileUtils.mkdir_p(File.join(logaling_config_path, "glossary"))
67
+
68
+ config = Logaling::Config.new("glossary" => project_name, "source-language" => source_language)
69
+ config.merge!("target-language" => target_language) if target_language
70
+ config.save(File.join(logaling_config_path, "config"))
71
+
72
+ unless options["no-register"]
73
+ @dotfile_path = options["logaling-config"] ? options["logaling-config"] : find_dotfile
74
+ @project_config_path = File.join(@dotfile_path, 'config')
75
+ @config.load(@project_config_path)
76
+ register
77
+ end
78
+ say "Successfully created #{logaling_config_path}"
79
+ else
80
+ say "#{logaling_config_path} already exists."
81
+ end
82
+ end
83
+
84
+ desc 'import', 'Import external glossary'
85
+ method_option "list", type: :boolean, default: false
86
+ def import(external_glossary=nil)
87
+ require "logaling/external_glossary"
88
+ Logaling::ExternalGlossary.load
89
+ if options["list"]
90
+ Logaling::ExternalGlossary.list.each {|glossary| say "#{glossary.name.bright} : #{glossary.description}" }
91
+ else
92
+ @repository.import(Logaling::ExternalGlossary.get(external_glossary))
93
+ @repository.index
94
+ end
95
+ rescue Logaling::ExternalGlossaryNotFound
96
+ say "'#{external_glossary}' can't find in import list."
97
+ say "Try 'loga import --list' and confirm import list."
98
+ end
99
+
100
+ desc 'register', 'Register .logaling'
101
+ def register
102
+ @config.check_required_option("glossary" => "input glossary name '-g <glossary name>'")
103
+ raise Logaling::CommandFailed, "Try 'loga new' first." unless File.exist?(@dotfile_path)
104
+
105
+ @repository.register(@dotfile_path, @config.glossary)
106
+ @repository.index
107
+ say "#{@config.glossary} is now registered to logaling."
108
+ rescue Logaling::CommandFailed => e
109
+ say e.message
110
+ rescue Logaling::GlossaryAlreadyRegistered => e
111
+ say "#{@config.glossary} is already registered."
112
+ end
113
+
114
+ desc 'unregister', 'Unregister .logaling'
115
+ def unregister
116
+ @config.check_required_option("glossary" => "input glossary name '-g <glossary name>'")
117
+
118
+ @repository.unregister(@config.glossary)
119
+ @repository.index
120
+ say "#{@config.glossary} is now unregistered."
121
+ rescue Logaling::CommandFailed => e
122
+ say e.message
123
+ rescue Logaling::GlossaryNotFound => e
124
+ say "#{@config.glossary} is not yet registered."
125
+ end
126
+
127
+ desc 'config [KEY] [VALUE] [--global(optional)]', 'Set config.'
128
+ method_option "global", type: :boolean, default: false
129
+ def config(key, value)
130
+ config_path = options["global"] ? File.join(@logaling_home, "config") : @project_config_path
131
+ config = Logaling::Config.load(config_path)
132
+ config.add(key, value)
133
+ config.save(config_path)
134
+ say "Successfully set config."
135
+ rescue Logaling::CommandFailed => e
136
+ say e.message
137
+ end
138
+
139
+ desc 'add [SOURCE TERM] [TARGET TERM] [NOTE(optional)]', 'Add term to glossary.'
140
+ def add(source_term, target_term, note='')
141
+ required_options = {
142
+ "glossary" => "input glossary name '-g <glossary name>'",
143
+ "source-language" => "input source-language code '-S <source-language code>'",
144
+ "target-language" => "input target-language code '-T <target-language code>'"
145
+ }
146
+ @config.check_required_option(required_options)
147
+ @repository.index
148
+
149
+ if @repository.bilingual_pair_exists?(source_term, target_term, @config.glossary)
150
+ raise Logaling::TermError, "term '#{source_term}: #{target_term}' already exists in '#{@config.glossary}'"
151
+ end
152
+
153
+ glossary.add(source_term, target_term, note)
154
+ rescue Logaling::CommandFailed, Logaling::TermError => e
155
+ say e.message
156
+ end
157
+
158
+ desc 'delete [SOURCE TERM] [TARGET TERM(optional)] [--force(optional)]', 'Delete term.'
159
+ method_option "force", type: :boolean, default: false
160
+ def delete(source_term, target_term=nil)
161
+ required_options = {
162
+ "glossary" => "input glossary name '-g <glossary name>'",
163
+ "source-language" => "input source-language code '-S <source-language code>'",
164
+ "target-language" => "input target-language code '-T <target-language code>'"
165
+ }
166
+ @config.check_required_option(required_options)
167
+
168
+ if target_term
169
+ glossary.delete(source_term, target_term)
170
+ else
171
+ glossary.delete_all(source_term, options["force"])
172
+ end
173
+ rescue Logaling::CommandFailed, Logaling::TermError => e
174
+ say e.message
175
+ rescue Logaling::GlossaryNotFound => e
176
+ say "Try 'loga new or register' first."
177
+ end
178
+
179
+ desc 'update [SOURCE TERM] [TARGET TERM] [NEW TARGET TERM] [NOTE(optional)]', 'Update term.'
180
+ def update(source_term, target_term, new_target_term, note='')
181
+ required_options = {
182
+ "glossary" => "input glossary name '-g <glossary name>'",
183
+ "source-language" => "input source-language code '-S <source-language code>'",
184
+ "target-language" => "input target-language code '-T <target-language code>'"
185
+ }
186
+ @config.check_required_option(required_options)
187
+ @repository.index
188
+
189
+ if @repository.bilingual_pair_exists_and_has_same_note?(source_term, new_target_term, note, @config.glossary)
190
+ raise Logaling::TermError, "term '#{source_term}: #{new_target_term}' already exists in '#{@config.glossary}'"
191
+ end
192
+
193
+ glossary.update(source_term, target_term, new_target_term, note)
194
+ rescue Logaling::CommandFailed, Logaling::TermError => e
195
+ say e.message
196
+ rescue Logaling::GlossaryNotFound => e
197
+ say "Try 'loga new or register' first."
198
+ end
199
+
200
+ desc 'lookup [TERM]', 'Lookup terms.'
201
+ method_option "output", type: :string, default: "terminal"
202
+ method_option "no-pager", type: :boolean, default: false
203
+ method_option "no-color", type: :boolean, default: false
204
+ method_option "dictionary", type: :boolean, default: false, aliases: "--dict"
205
+ def lookup(source_term)
206
+ @repository.index
207
+ terms = @repository.lookup(source_term, glossary, options["dictionary"])
208
+ unless terms.empty?
209
+ max_str_size = terms.map{|term| term[:source_term].size}.sort.last
210
+ run_pager
211
+ terms.each_with_index do |term, i|
212
+ source_string = extract_keyword_and_coloring(term[:snipped_source_term], term[:source_term])
213
+ target_string = extract_keyword_and_coloring(term[:snipped_target_term], term[:target_term])
214
+ note = term[:note].to_s unless term[:note].empty?
215
+ glossary_name = ""
216
+ if @repository.glossary_counts > 1
217
+ glossary_name = term[:glossary_name]
218
+ if term[:glossary_name] == @config.glossary
219
+ glossary_name = glossary_name.foreground(:white).background(:green)
220
+ end
221
+ end
222
+ printer(source_string, target_string, note,
223
+ glossary_name, max_str_size, i, terms.length)
224
+ end
225
+ else
226
+ "source-term <#{source_term}> not found"
227
+ end
228
+ rescue Logaling::CommandFailed, Logaling::TermError => e
229
+ say e.message
230
+ end
231
+
232
+ desc 'version', 'Show version.'
233
+ def version
234
+ say "logaling-command version #{Logaling::Command::VERSION}"
235
+ end
236
+
237
+ desc 'show', 'Show terms in glossary.'
238
+ method_option "no-pager", type: :boolean, default: false
239
+ def show
240
+ required_options = {
241
+ "glossary" => "input glossary name '-g <glossary name>'",
242
+ "source-language" => "input source-language code '-S <source-language code>'",
243
+ "target-language" => "input target-language code '-T <target-language code>'"
244
+ }
245
+ @config.check_required_option(required_options)
246
+ @repository.index
247
+ terms = @repository.show_glossary(glossary)
248
+ unless terms.empty?
249
+ run_pager
250
+ max_str_size = terms.map{|term| term[:source_term].size}.sort.last
251
+ terms.each do |term|
252
+ target_string = "#{term[:target_term]}"
253
+ target_string << "\t# #{term[:note]}" unless term[:note].empty?
254
+ printf(" %-#{max_str_size+10}s %s\n", term[:source_term], target_string)
255
+ end
256
+ else
257
+ "glossary <#{@config.glossary}> not found"
258
+ end
259
+
260
+ rescue Logaling::CommandFailed, Logaling::GlossaryDBNotFound => e
261
+ say e.message
262
+ end
263
+
264
+ desc 'list', 'Show glossary list.'
265
+ method_option "no-pager", type: :boolean, default: false
266
+ def list
267
+ @repository.index
268
+ glossaries = @repository.list
269
+ unless glossaries.empty?
270
+ run_pager
271
+ glossaries.each do |glossary|
272
+ printf(" %s\n", glossary)
273
+ end
274
+ else
275
+ "There is no registered glossary."
276
+ end
277
+
278
+ rescue Logaling::CommandFailed, Logaling::GlossaryDBNotFound => e
279
+ say e.message
280
+ end
281
+
282
+ private
283
+ def glossary
284
+ @glossary ||= Logaling::Glossary.new(@config.glossary, @config.source_language, @config.target_language, @logaling_home)
285
+ end
286
+
287
+ def error(msg)
288
+ STDERR.puts(msg)
289
+ exit 1
290
+ end
291
+
292
+ def find_dotfile
293
+ dir = Dir.pwd
294
+ searched_path = []
295
+ while(dir) do
296
+ path = File.join(dir, '.logaling')
297
+ if File.exist?(path)
298
+ return path
299
+ else
300
+ if dir != "/"
301
+ searched_path << dir
302
+ dir = File.dirname(dir)
303
+ else
304
+ raise(Logaling::CommandFailed, "Can't found .logaling in #{searched_path}")
305
+ end
306
+ end
307
+ end
308
+ end
309
+
310
+ def logaling_config_path
311
+ if options["logaling-config"]
312
+ options["logaling-config"]
313
+ else
314
+ File.join(Dir.pwd, LOGALING_CONFIG)
315
+ end
316
+ end
317
+
318
+ # http://nex-3.com/posts/73-git-style-automatic-paging-in-ruby
319
+ def run_pager
320
+ return if options["no-pager"]
321
+ return if ::RUBY_PLATFORM =~ /win32/
322
+ return unless STDOUT.tty?
323
+
324
+ read, write = IO.pipe
325
+
326
+ unless Kernel.fork # Child process
327
+ STDOUT.reopen(write)
328
+ STDERR.reopen(write) if STDERR.tty?
329
+ read.close
330
+ write.close
331
+ return
332
+ end
333
+
334
+ # Parent process, become pager
335
+ STDIN.reopen(read)
336
+ read.close
337
+ write.close
338
+
339
+ ENV['LESS'] = 'FSRX' # Don't page if the input is short enough
340
+
341
+ # wait until we have input before we start the pager
342
+ Kernel.select [STDIN]
343
+ pager = ENV['PAGER'] || 'less'
344
+ exec pager rescue exec "/bin/sh", "-c", pager
345
+ end
346
+
347
+ def extract_keyword_and_coloring(snipped_term, term)
348
+ return term if snipped_term.empty? || options["no-color"]
349
+ display_string = snipped_term.map do |word|
350
+ word.is_a?(Hash) ? word[:keyword].bright : word
351
+ end
352
+ display_string = display_string.join
353
+ display_string
354
+ end
355
+
356
+ def printer(source_string, target_string, note=nil,
357
+ glossary_name, max_str_size, i, last)
358
+ case options["output"]
359
+ when "terminal"
360
+ unless note
361
+ format = target_string + "\t" + glossary_name
362
+ else
363
+ format = target_string + "\t# " + note + "\t" + glossary_name
364
+ end
365
+ printf(" %-#{max_str_size+10}s %s\n", source_string, format)
366
+ when "csv"
367
+ items = [source_string, target_string, note,
368
+ @config.source_language, @config.target_language]
369
+ print(CSV.generate {|csv| csv << items})
370
+ when "json"
371
+ puts("[") if i == 0
372
+ puts(",") if i > 0
373
+ record = {
374
+ :source => source_string, :target => target_string, :note => note,
375
+ :source_language => @config.source_language,
376
+ :target_language => @config.target_language
377
+ }
378
+ print JSON.pretty_generate(record)
379
+ puts("\n]") if i == last-1
380
+ end
381
+ end
382
+ end
383
+ end
@@ -0,0 +1,22 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # Copyright (C) 2011 Miho SUZUKI
4
+ #
5
+ # This program is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # This program is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
17
+
18
+ module Logaling
19
+ module Command
20
+ VERSION = "0.1.3"
21
+ end
22
+ end