logaling-command 0.1.2 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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