logaling-command 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in logaling-command.gemspec
4
+ gemspec
data/Rakefile ADDED
@@ -0,0 +1,9 @@
1
+ require 'bundler/gem_tasks'
2
+ require "rspec/core/rake_task"
3
+
4
+ desc "Run all specs"
5
+ RSpec::Core::RakeTask.new(:spec) do |t|
6
+ t.verbose = true
7
+ end
8
+
9
+ task :default => :spec
data/bin/loga ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ lib = File.expand_path(File.dirname(__FILE__) + '/../lib')
4
+ $LOAD_PATH.unshift(lib) if File.directory?(lib) && !$LOAD_PATH.include?(lib)
5
+ LOGALING_HOME = File.expand_path("~/.logaling.d")
6
+
7
+ require "logaling"
8
+
9
+ Logaling::Command.start
10
+
@@ -0,0 +1,135 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'thor'
4
+ require "logaling/glossary"
5
+ require "logaling/glossary_db"
6
+
7
+ class Logaling::Command < Thor
8
+ VERSION = "0.0.1"
9
+
10
+ map '-c' => :create,
11
+ '-a' => :add,
12
+ '-d' => :delete,
13
+ '-u' => :update,
14
+ '-l' => :lookup
15
+
16
+ class_option :glossary, type: :string, aliases: "-g"
17
+ class_option :source_language, type: :string, aliases: "-S"
18
+ class_option :target_language, type: :string, aliases: "-T"
19
+ class_option :logaling_home, type: :string, required: false, aliases: "-h"
20
+
21
+ def initialize(*args)
22
+ super
23
+ @dot_options = Hash.new
24
+ end
25
+
26
+ desc 'create', 'Create glossary.'
27
+ def create
28
+ load_config
29
+ glossary.create
30
+ rescue Logaling::CommandFailed => e
31
+ error(e.message)
32
+ end
33
+
34
+ desc 'add', 'Add term to glossary.'
35
+ method_option :source_term, type: :string, required: true, aliases: "-s"
36
+ method_option :target_term, type: :string, required: true, aliases: "-t"
37
+ method_option :note, type: :string, aliases: "-n"
38
+ def add
39
+ load_config
40
+ glossary.add(options[:source_term], options[:target_term], options[:note])
41
+ rescue Logaling::CommandFailed => e
42
+ error(e.message)
43
+ end
44
+
45
+ desc 'delete', 'Delete term.'
46
+ method_option :source_term, type: :string, required: true, aliases: "-s"
47
+ method_option :target_term, type: :string, required: true, aliases: "-t"
48
+ def delete
49
+ load_config
50
+ glossary.delete(options[:source_term], options[:target_term])
51
+ rescue Logaling::CommandFailed => e
52
+ error(e.message)
53
+ end
54
+
55
+ desc 'update', 'Update term.'
56
+ method_option :source_term, type: :string, required: true, aliases: "-s"
57
+ method_option :target_term, type: :string, required: true, aliases: "-t"
58
+ method_option :new_target_term, type: :string, required: true, aliases: "-nt"
59
+ method_option :note, type: :string, required: true, aliases: "-n"
60
+ def update
61
+ load_config
62
+ glossary.update(options[:source_term], options[:target_term], options[:new_target_term], options[:note])
63
+ rescue Logaling::CommandFailed => e
64
+ error(e.message)
65
+ end
66
+
67
+ desc 'lookup', 'Lookup terms.'
68
+ method_option :source_term, type: :string, required: true, aliases: "-s"
69
+ def lookup
70
+ load_config
71
+ glossary.lookup(options[:source_term])
72
+ rescue Logaling::CommandFailed => e
73
+ error(e.message)
74
+ end
75
+
76
+ desc 'index', 'Index glossaries to groonga DB.'
77
+ def index
78
+ load_config
79
+ home = find_option("logaling_home") || LOGALING_HOME
80
+ db_home = File.join(home, ".logadb")
81
+ glossarydb = Logaling::GlossaryDB.new
82
+ glossarydb.open(db_home, "utf8") do |db|
83
+ db.recreate_table(db_home)
84
+ db.load_glossaries(home)
85
+ end
86
+ end
87
+
88
+ private
89
+ def glossary
90
+ glossary = find_option("glossary")
91
+ raise(Logaling::CommandFailed, "input glossary name '-g <glossary name>'") unless glossary
92
+
93
+ source_language = find_option("source_language")
94
+ raise(Logaling::CommandFailed, "input source-language code '-S <source-language code>'") unless source_language
95
+
96
+ target_language = find_option("target_language")
97
+ raise(Logaling::CommandFailed, "input target-language code '-T <target-language code>'") unless target_language
98
+
99
+ logaling_home = find_option("logaling_home")
100
+
101
+ Logaling::Glossary.new(glossary, source_language, target_language, logaling_home)
102
+ end
103
+
104
+ def error(msg)
105
+ STDERR.puts(msg)
106
+ exit 1
107
+ end
108
+
109
+ def find_option(key)
110
+ options[key] || @dot_options[key]
111
+ end
112
+
113
+ def load_config
114
+ if path = find_dotfile
115
+ tmp_options = File.readlines(path).map {|l| l.chomp.split " "}
116
+ tmp_options.each do |option|
117
+ key = option[0].sub(/^[\-]{2}/, "")
118
+ value = option[1]
119
+ @dot_options[key] = value
120
+ end
121
+ end
122
+ end
123
+
124
+ def find_dotfile
125
+ dir = Dir.pwd
126
+ while(dir) do
127
+ path = File.join(dir, '.logaling')
128
+ if File.exist?(path)
129
+ return path
130
+ break
131
+ end
132
+ dir = (dir != "/") ? File.dirname(dir) : nil
133
+ end
134
+ end
135
+ end
@@ -0,0 +1,175 @@
1
+ # -*- coding: utf-8 -*-
2
+ #require "logaling-command/version"
3
+
4
+ require 'psych'
5
+ require "yaml"
6
+ require "fileutils"
7
+
8
+ module Logaling
9
+ class Glossary
10
+ def self.build_path(glossary, source_language, target_language, logaling_home)
11
+ dir, file = File::split(glossary)
12
+ if dir == "."
13
+ fname = [glossary, source_language, target_language].join(".")
14
+ return File.join(logaling_home, "#{fname}.yml")
15
+ else
16
+ return glossary
17
+ end
18
+ end
19
+
20
+ def initialize(glossary, source_language, target_language, logaling_home)
21
+ logaling_home ||= LOGALING_HOME
22
+ @path = Glossary.build_path(glossary, source_language, target_language, logaling_home)
23
+ @glossary = glossary
24
+ @source_language = source_language
25
+ @target_language = target_language
26
+ @logaling_home = logaling_home
27
+ end
28
+
29
+ def create
30
+ check_glossary_unexists
31
+
32
+ dirname = File::dirname(@path)
33
+ FileUtils.mkdir_p(dirname)
34
+ FileUtils.touch(@path)
35
+ end
36
+
37
+ def add(source_term, target_term, note)
38
+ check_glossary_exists
39
+
40
+ if bilingual_pair_exists?(source_term, target_term)
41
+ puts "[#{source_term}] [#{target_term}] pair already exists"
42
+ return
43
+ end
44
+
45
+ glossary = load_glossary_yml
46
+ glossary << build_term(source_term, target_term, note)
47
+
48
+ dump_glossary(glossary)
49
+ end
50
+
51
+ def update(source_term, target_term, new_target_term, note)
52
+ check_glossary_exists
53
+
54
+ if bilingual_pair_exists?(source_term, new_target_term)
55
+ puts "[#{source_term}] [#{new_target_term}] pair already exists"
56
+ return
57
+ end
58
+
59
+ glossary = load_glossary_yml
60
+ target_index = find_term_index(glossary, source_term, target_term)
61
+ if target_index
62
+ glossary[target_index] = rebuild_term(glossary[target_index], source_term, new_target_term, note)
63
+ dump_glossary(glossary)
64
+ else
65
+ puts "source_term:#{source_term} target_term:#{target_term} not found in glossary #{@path}"
66
+ end
67
+ end
68
+
69
+ def delete(source_term, target_term)
70
+ check_glossary_exists
71
+
72
+ glossary = load_glossary_yml
73
+ target_index = find_term_index(glossary, source_term, target_term)
74
+ if target_index
75
+ glossary.delete_at(target_index)
76
+ dump_glossary(glossary)
77
+ else
78
+ puts "source_term:#{source_term} target_term:#{target_term} not found in glossary #{@path}"
79
+ end
80
+ end
81
+
82
+ def lookup(source_term)
83
+ check_glossary_exists
84
+
85
+ glossarydb = Logaling::GlossaryDB.new
86
+ glossarydb.open(logaling_db_home, "utf8") do |db|
87
+ glossaries = db.lookup(source_term)
88
+ glossaries.reject! do |term|
89
+ term[:source_language] != @source_language || term[:target_language] != @target_language
90
+ end
91
+ if glossaries.empty?
92
+ puts "source_term <#{source_term}> not found"
93
+ return
94
+ end
95
+ # order by glossary
96
+ specified = glossaries.select{|term| term[:name] == @glossary}
97
+ other = glossaries.select{|term| term[:name] != @glossary}
98
+ glossaries = specified.concat(other)
99
+
100
+ puts "\nlookup word : #{source_term}"
101
+ glossaries.each do |term|
102
+ puts "\n #{term[:source_term]}\n"
103
+ puts " #{term[:target_term]}\n"
104
+ puts " note:#{term[:note]}"
105
+ puts " glossary:#{term[:name]}"
106
+ end
107
+ end
108
+ end
109
+
110
+ private
111
+ def load_glossary_yml
112
+ YAML::load_file(@path) || []
113
+ end
114
+
115
+ def logaling_db_home
116
+ File.join(@logaling_home, ".logadb")
117
+ end
118
+
119
+ def build_term(source_term, target_term, note)
120
+ {'source_term' => source_term, 'target_term' => target_term, 'note' => note}
121
+ end
122
+
123
+ def rebuild_term(current, source_term, target_term, note)
124
+ note = current['note'] if note == ""
125
+ target_term = current['target_term'] if target_term == ""
126
+ build_term(source_term, target_term, note)
127
+ end
128
+
129
+ def find_term_index(glossary_yml, source_term, target_term)
130
+ glossary_yml.find_index do |term|
131
+ term['source_term'] == source_term && term['target_term'] == target_term
132
+ end
133
+ end
134
+
135
+ def bilingual_pair_exists?(source_term, target_term)
136
+ target_terms(source_term).any?{|data| data['target_term'] == target_term }
137
+ end
138
+
139
+ def exist?
140
+ File.exists?(@path)
141
+ end
142
+
143
+ def check_glossary_unexists
144
+ raise CommandFailed, "glossary #{@path} already exists" if exist?
145
+ end
146
+
147
+ def check_glossary_exists
148
+ raise CommandFailed, "glossary #{@path} not found" unless exist?
149
+ end
150
+
151
+ def target_terms(source_term, path=@path)
152
+ target_terms = []
153
+ glossaly = YAML::load_file(path) || []
154
+ glossaly.each do |term|
155
+ target_terms << term if term['source_term'] == source_term
156
+ end
157
+ target_terms
158
+ end
159
+
160
+ def lookup_files
161
+ file_list = Dir.glob("#{@logaling_home}/*.#{@source_language}.#{@target_language}.yml")
162
+ if glossary_index = file_list.index(@path)
163
+ file_list.delete_at(glossary_index)
164
+ end
165
+ file_list.unshift(@path)
166
+ return file_list
167
+ end
168
+
169
+ def dump_glossary(glossary)
170
+ File.open(@path, "w") do |f|
171
+ f.puts(glossary.to_yaml)
172
+ end
173
+ end
174
+ end
175
+ end
@@ -0,0 +1,132 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'psych'
4
+ require "yaml"
5
+ require "fileutils"
6
+ require 'groonga'
7
+
8
+ module Logaling
9
+ class GlossaryDB
10
+ def initialize()
11
+ @database = nil
12
+ end
13
+
14
+ def open(base_path, encoding)
15
+ reset_context(encoding)
16
+ path = File.join(base_path, "logaling.db")
17
+ if File.exist?(path)
18
+ @database = Groonga::Database.open(path)
19
+ else
20
+ FileUtils.mkdir_p(base_path)
21
+ populate(path)
22
+ end
23
+ if block_given?
24
+ begin
25
+ yield(self)
26
+ ensure
27
+ close unless closed?
28
+ end
29
+ end
30
+ end
31
+
32
+ def recreate_table(base_path)
33
+ path = File.join(base_path, "logaling.db.tables")
34
+ if File.exist?(path)
35
+ remove_schema
36
+ end
37
+ populate_schema
38
+ end
39
+
40
+ def close
41
+ @database.close
42
+ @database = nil
43
+ end
44
+
45
+ def closed?
46
+ @database.nil? or @database.closed?
47
+ end
48
+
49
+ def load_glossaries(path)
50
+ file_list = Dir.glob("#{path}/*.yml")
51
+ file_list.each do |file|
52
+ name, source_language, target_language = File::basename(file, "yml").split(".")
53
+ glossary = YAML::load_file(file)
54
+ next if !glossary
55
+ glossary.each do |term|
56
+ source_term = term['source_term']
57
+ target_term = term['target_term']
58
+ note = term['note']
59
+ add_glossary(name, source_language, target_language, source_term, target_term, note)
60
+ end
61
+ end
62
+ end
63
+
64
+ def lookup(source_term)
65
+ records_raw = Groonga["glossaries"].select do |record|
66
+ record.source_term =~ source_term
67
+ end
68
+ records = records_raw.sort([
69
+ {:key=>"name", :order=>'ascending'},
70
+ {:key=>"source_term", :order=>'ascending'},
71
+ {:key=>"target_term", :order=>'ascending'}])
72
+
73
+ records.map do |record|
74
+ term = record.key
75
+ {:name => term.name,
76
+ :source_language => term.source_language,
77
+ :target_language => term.target_language,
78
+ :source_term => term.source_term,
79
+ :target_term => term.target_term,
80
+ :note => term.note,}
81
+ end
82
+ end
83
+
84
+ private
85
+ def add_glossary(name, source_language, target_language, source_term, target_term, note)
86
+ Groonga["glossaries"].add(:name => name,
87
+ :source_language => source_language,
88
+ :target_language => target_language,
89
+ :source_term => source_term,
90
+ :target_term => target_term,
91
+ :note => note,
92
+ )
93
+ end
94
+
95
+ def reset_context(encoding)
96
+ Groonga::Context.default_options = {:encoding => encoding}
97
+ Groonga::Context.default = nil
98
+ end
99
+
100
+ def populate(path)
101
+ @database = Groonga::Database.create(:path => path)
102
+ end
103
+
104
+ def populate_schema
105
+ Groonga::Schema.define do |schema|
106
+ schema.create_table("glossaries") do |table|
107
+ table.short_text("name")
108
+ table.short_text("source_language")
109
+ table.short_text("target_language")
110
+ table.short_text("source_term")
111
+ table.text("target_term")
112
+ table.text("note")
113
+ end
114
+
115
+ schema.create_table("terms",
116
+ :type => :patricia_trie,
117
+ :key_type => "ShortText",
118
+ :key_normalize => true,
119
+ :default_tokenizer => "TokenBigram") do |table|
120
+ table.index("glossaries.source_term")
121
+ end
122
+ end
123
+ end
124
+
125
+ def remove_schema
126
+ Groonga::Schema.define do |schema|
127
+ schema.remove_table("glossaries")
128
+ schema.remove_table("terms")
129
+ end
130
+ end
131
+ end
132
+ end
data/lib/logaling.rb ADDED
@@ -0,0 +1,7 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require "logaling/command"
4
+
5
+ module Logaling
6
+ class CommandFailed < RuntimeError; end
7
+ end
@@ -0,0 +1,23 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "logaling/command.rb"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "logaling-command"
7
+ s.version = Logaling::Command::VERSION
8
+ s.authors = ["SHIMADA Koji", "SHIDARA Yoji", "Kouhei Sutou", "Daijiro MORI", "SUZUKI Miho"]
9
+ s.email = ["koji.shimada@enishi-tech.com", "dara@shidara.net", "kou@clear-code.com", "daijiro.mori@gmail.com", "adzuki34@gmail.com"]
10
+ s.homepage = "http://logaling.github.com/"
11
+ s.summary = %q{A command line interface for logaling.}
12
+ s.description = %q{A command line interface for logaling.}
13
+
14
+ s.rubyforge_project = "logaling-command"
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+
21
+ s.add_development_dependency 'rake'
22
+ s.add_development_dependency 'rspec'
23
+ end
@@ -0,0 +1,8 @@
1
+ require "rubygems"
2
+ require "bundler/setup"
3
+
4
+ require 'rspec'
5
+ $LOAD_PATH.unshift(File.dirname(__FILE__) + '/../lib')
6
+
7
+ require 'logaling_command'
8
+
metadata ADDED
@@ -0,0 +1,88 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: logaling-command
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - SHIMADA Koji
9
+ - SHIDARA Yoji
10
+ - Kouhei Sutou
11
+ - Daijiro MORI
12
+ - SUZUKI Miho
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+ date: 2011-11-09 00:00:00.000000000Z
17
+ dependencies:
18
+ - !ruby/object:Gem::Dependency
19
+ name: rake
20
+ requirement: &2151902900 !ruby/object:Gem::Requirement
21
+ none: false
22
+ requirements:
23
+ - - ! '>='
24
+ - !ruby/object:Gem::Version
25
+ version: '0'
26
+ type: :development
27
+ prerelease: false
28
+ version_requirements: *2151902900
29
+ - !ruby/object:Gem::Dependency
30
+ name: rspec
31
+ requirement: &2151901960 !ruby/object:Gem::Requirement
32
+ none: false
33
+ requirements:
34
+ - - ! '>='
35
+ - !ruby/object:Gem::Version
36
+ version: '0'
37
+ type: :development
38
+ prerelease: false
39
+ version_requirements: *2151901960
40
+ description: A command line interface for logaling.
41
+ email:
42
+ - koji.shimada@enishi-tech.com
43
+ - dara@shidara.net
44
+ - kou@clear-code.com
45
+ - daijiro.mori@gmail.com
46
+ - adzuki34@gmail.com
47
+ executables:
48
+ - loga
49
+ extensions: []
50
+ extra_rdoc_files: []
51
+ files:
52
+ - .gitignore
53
+ - .rspec
54
+ - Gemfile
55
+ - Rakefile
56
+ - bin/loga
57
+ - lib/logaling.rb
58
+ - lib/logaling/command.rb
59
+ - lib/logaling/glossary.rb
60
+ - lib/logaling/glossary_db.rb
61
+ - logaling-command.gemspec
62
+ - spec/spec_helper.rb
63
+ homepage: http://logaling.github.com/
64
+ licenses: []
65
+ post_install_message:
66
+ rdoc_options: []
67
+ require_paths:
68
+ - lib
69
+ required_ruby_version: !ruby/object:Gem::Requirement
70
+ none: false
71
+ requirements:
72
+ - - ! '>='
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ required_rubygems_version: !ruby/object:Gem::Requirement
76
+ none: false
77
+ requirements:
78
+ - - ! '>='
79
+ - !ruby/object:Gem::Version
80
+ version: '0'
81
+ requirements: []
82
+ rubyforge_project: logaling-command
83
+ rubygems_version: 1.8.6
84
+ signing_key:
85
+ specification_version: 3
86
+ summary: A command line interface for logaling.
87
+ test_files:
88
+ - spec/spec_helper.rb