lingo 1.8.1 → 1.8.2
Sign up to get free protection for your applications and to get access to all the features.
- data/ChangeLog +23 -5
- data/README +1 -1
- data/Rakefile +5 -7
- data/TODO +2 -0
- data/bin/lingo +5 -1
- data/de.lang +1 -1
- data/en/lingo-syn.txt +0 -0
- data/en.lang +2 -1
- data/lib/lingo/attendee/abbreviator.rb +8 -9
- data/lib/lingo/attendee/debugger.rb +5 -4
- data/lib/lingo/attendee/decomposer.rb +8 -3
- data/lib/lingo/attendee/dehyphenizer.rb +19 -63
- data/lib/lingo/attendee/formatter.rb +1 -1
- data/lib/lingo/attendee/multi_worder.rb +67 -155
- data/lib/lingo/attendee/noneword_filter.rb +16 -9
- data/lib/lingo/attendee/object_filter.rb +1 -1
- data/lib/lingo/attendee/sequencer.rb +32 -63
- data/lib/lingo/attendee/stemmer/porter.rb +343 -0
- data/{info/gpl-hdr.txt → lib/lingo/attendee/stemmer.rb} +33 -0
- data/lib/lingo/attendee/synonymer.rb +10 -9
- data/lib/lingo/attendee/text_reader.rb +102 -76
- data/lib/lingo/attendee/text_writer.rb +23 -26
- data/lib/lingo/attendee/tokenizer.rb +13 -27
- data/lib/lingo/attendee/variator.rb +26 -66
- data/lib/lingo/attendee/vector_filter.rb +42 -43
- data/lib/lingo/attendee/word_searcher.rb +6 -7
- data/lib/lingo/attendee.rb +25 -7
- data/lib/lingo/buffered_attendee.rb +36 -10
- data/lib/lingo/cachable.rb +8 -8
- data/lib/lingo/config.rb +5 -6
- data/lib/lingo/ctl.rb +2 -3
- data/lib/lingo/database/crypter.rb +9 -26
- data/lib/lingo/database/gdbm_store.rb +3 -5
- data/lib/lingo/database/libcdb_store.rb +4 -6
- data/lib/lingo/database/sdbm_store.rb +11 -6
- data/lib/lingo/database/show_progress.rb +3 -43
- data/lib/lingo/database/source/key_value.rb +2 -6
- data/lib/lingo/database/source/multi_key.rb +3 -5
- data/lib/lingo/database/source/multi_value.rb +2 -6
- data/lib/lingo/database/source/single_word.rb +4 -6
- data/lib/lingo/database/source/word_class.rb +4 -10
- data/lib/lingo/database/source.rb +20 -18
- data/lib/lingo/database.rb +84 -59
- data/lib/lingo/error.rb +57 -1
- data/lib/lingo/language/dictionary.rb +21 -18
- data/lib/lingo/language/grammar.rb +40 -49
- data/lib/lingo/language/lexical.rb +6 -6
- data/lib/lingo/language/lexical_hash.rb +6 -0
- data/lib/lingo/language/word.rb +32 -15
- data/lib/lingo/language/word_form.rb +1 -1
- data/lib/lingo/language.rb +14 -25
- data/lib/lingo/reportable.rb +12 -10
- data/lib/lingo/show_progress.rb +81 -0
- data/lib/lingo/version.rb +1 -1
- data/lib/lingo.rb +63 -24
- data/lingo-call.cfg +6 -10
- data/lingo.cfg +60 -44
- data/lir.cfg +42 -41
- data/test/attendee/ts_abbreviator.rb +3 -5
- data/test/attendee/ts_decomposer.rb +3 -5
- data/test/attendee/ts_multi_worder.rb +87 -145
- data/test/attendee/ts_noneword_filter.rb +5 -3
- data/test/attendee/ts_object_filter.rb +5 -3
- data/test/attendee/ts_sequencer.rb +3 -5
- data/test/attendee/ts_stemmer.rb +309 -0
- data/test/attendee/ts_synonymer.rb +15 -11
- data/test/attendee/ts_text_reader.rb +12 -15
- data/test/attendee/ts_text_writer.rb +24 -29
- data/test/attendee/ts_tokenizer.rb +9 -7
- data/test/attendee/ts_variator.rb +4 -4
- data/test/attendee/ts_vector_filter.rb +24 -16
- data/test/attendee/ts_word_searcher.rb +20 -36
- data/test/{lir.csv → lir.vec} +0 -0
- data/test/ref/artikel.vec +943 -943
- data/test/ref/artikel.ven +943 -943
- data/test/ref/lir.non +201 -201
- data/test/ref/lir.seq +178 -178
- data/test/ref/lir.syn +49 -49
- data/test/ref/lir.vec +329 -0
- data/test/test_helper.rb +20 -36
- data/test/ts_database.rb +10 -10
- data/test/ts_language.rb +279 -319
- metadata +93 -104
- data/info/Objekte.png +0 -0
- data/info/Typen.png +0 -0
- data/info/database.png +0 -0
- data/info/db_small.png +0 -0
- data/info/download.png +0 -0
- data/info/kerze.png +0 -0
- data/info/language.png +0 -0
- data/info/lingo.png +0 -0
- data/info/logo.png +0 -0
- data/info/meeting.png +0 -0
- data/info/types.png +0 -0
- data/lingo-all.cfg +0 -89
- data/porter/stem.cfg +0 -311
- data/porter/stem.rb +0 -150
- data/test/ref/lir.csv +0 -329
- data/test.cfg +0 -79
@@ -38,17 +38,15 @@ class Lingo
|
|
38
38
|
|
39
39
|
def initialize(id, lingo)
|
40
40
|
super
|
41
|
-
|
42
|
-
@
|
43
|
-
@
|
44
|
-
|
45
|
-
@line_pattern = %r{^(#{@legal_word})$}
|
41
|
+
@pat = /^(#{@wrd})$/
|
42
|
+
@def = @config.fetch('def-wc', 's').downcase
|
43
|
+
@mul = @config.fetch('def-mul-wc', @def).downcase
|
46
44
|
end
|
47
45
|
|
48
46
|
private
|
49
47
|
|
50
48
|
def convert_line(line, key, val)
|
51
|
-
[key = key.strip, %W[##{key =~ /\s/ ? @
|
49
|
+
[key = key.strip, %W[##{key =~ /\s/ ? @mul : @def}]]
|
52
50
|
end
|
53
51
|
|
54
52
|
end
|
@@ -38,21 +38,15 @@ class Lingo
|
|
38
38
|
|
39
39
|
def initialize(id, lingo)
|
40
40
|
super
|
41
|
-
|
42
|
-
@separator = @config.fetch('separator', ',')
|
43
|
-
@line_pattern = Regexp.new('^(' + @legal_word + ')' + Regexp.escape(@separator) + '((?:' + @legal_word + '#\w)+)$')
|
41
|
+
@pat = /^(#{@wrd})#{Regexp.escape(@sep ||= ',')}((?:#{@wrd}#\w)+)$/
|
44
42
|
end
|
45
43
|
|
46
44
|
private
|
47
45
|
|
48
46
|
def convert_line(line, key, val)
|
49
|
-
key
|
50
|
-
|
51
|
-
|
52
|
-
str =~ /^(.+)#(.)/
|
53
|
-
($1 == key ? '' : $1) + '#' + $2
|
54
|
-
end
|
55
|
-
[key, val]
|
47
|
+
[key = key.strip, val.strip.scan(/(\S.+?)\s*#(\w)/).map! { |v, c|
|
48
|
+
"#{v unless key == v}##{c}"
|
49
|
+
}]
|
56
50
|
end
|
57
51
|
|
58
52
|
end
|
@@ -63,52 +63,54 @@ class Lingo
|
|
63
63
|
UTF8_CHAR = "#{UTF8_DIGIT}|#{UTF8_BASLAT}|#{UTF8_LAT1SP}|#{UTF8_LATEXA}|#{UTF8_LATEXB}|#{UTF8_IPAEXT}"
|
64
64
|
|
65
65
|
PRINTABLE_CHAR = "#{UTF8_CHAR}|[<>-]"
|
66
|
+
LEGAL_CHAR = '[ /&()\[\].,-]'
|
66
67
|
|
67
68
|
def self.get(name, *args)
|
68
|
-
|
69
|
+
Lingo.get_const(name, self).new(*args)
|
69
70
|
end
|
70
71
|
|
71
|
-
attr_reader :
|
72
|
+
attr_reader :pos
|
72
73
|
|
73
74
|
def initialize(id, lingo)
|
74
75
|
@config = lingo.database_config(id)
|
75
76
|
|
76
|
-
source_file = Lingo.find(:dict, name = @config['name'])
|
77
|
+
source_file = Lingo.find(:dict, name = @config['name'], relax: true)
|
78
|
+
|
77
79
|
reject_file = begin
|
78
80
|
Lingo.find(:store, source_file) << '.rev'
|
79
|
-
rescue NoWritableStoreError
|
81
|
+
rescue NoWritableStoreError, SourceFileNotFoundError
|
80
82
|
end
|
81
83
|
|
82
|
-
@
|
83
|
-
@
|
84
|
+
@src = Pathname.new(source_file)
|
85
|
+
@rej = Pathname.new(reject_file) if reject_file
|
84
86
|
|
85
|
-
raise SourceFileNotFoundError.new(name, id) unless @
|
87
|
+
raise SourceFileNotFoundError.new(name, id) unless @src.exist?
|
86
88
|
|
87
|
-
@
|
88
|
-
@
|
89
|
+
@def = @config.fetch('def-wc', Language::LA_UNKNOWN).downcase
|
90
|
+
@sep = @config['separator']
|
89
91
|
|
90
|
-
@
|
91
|
-
@
|
92
|
+
@wrd = "(?:#{PRINTABLE_CHAR}|#{LEGAL_CHAR})+"
|
93
|
+
@pat = /^#{@wrd}$/
|
92
94
|
|
93
|
-
@
|
95
|
+
@pos = 0
|
94
96
|
end
|
95
97
|
|
96
98
|
def size
|
97
|
-
@
|
99
|
+
@src.size
|
98
100
|
end
|
99
101
|
|
100
102
|
def each
|
101
|
-
reject_file = @
|
103
|
+
reject_file = @rej.open('w', encoding: ENC) if @rej
|
102
104
|
|
103
|
-
@
|
104
|
-
@
|
105
|
+
@src.each_line($/, encoding: ENC) { |line|
|
106
|
+
@pos += length = line.bytesize
|
105
107
|
|
106
108
|
next if line =~ /\A\s*#/ || line.strip.empty?
|
107
109
|
|
108
110
|
line.chomp!
|
109
111
|
line.downcase!
|
110
112
|
|
111
|
-
if length < 4096 && line =~ @
|
113
|
+
if length < 4096 && line =~ @pat
|
112
114
|
yield convert_line(line, $1, $2)
|
113
115
|
else
|
114
116
|
reject_file.puts(line) if reject_file
|
@@ -119,7 +121,7 @@ class Lingo
|
|
119
121
|
ensure
|
120
122
|
if reject_file
|
121
123
|
reject_file.close
|
122
|
-
@
|
124
|
+
@rej.delete if @rej.size == 0
|
123
125
|
end
|
124
126
|
end
|
125
127
|
|
data/lib/lingo/database.rb
CHANGED
@@ -24,17 +24,9 @@
|
|
24
24
|
###############################################################################
|
25
25
|
#++
|
26
26
|
|
27
|
-
require 'pathname'
|
28
|
-
require 'fileutils'
|
29
|
-
require 'digest/sha1'
|
30
|
-
|
31
27
|
require_relative 'database/show_progress'
|
32
28
|
require_relative 'database/crypter'
|
33
29
|
require_relative 'database/source'
|
34
|
-
require_relative 'database/hash_store'
|
35
|
-
require_relative 'database/sdbm_store'
|
36
|
-
require_relative 'database/gdbm_store'
|
37
|
-
require_relative 'database/libcdb_store'
|
38
30
|
|
39
31
|
class Lingo
|
40
32
|
|
@@ -49,45 +41,57 @@ class Lingo
|
|
49
41
|
|
50
42
|
include Cachable
|
51
43
|
|
52
|
-
BACKENDS = %w[LibCDB SDBM GDBM].unshift(ENV['LINGO_BACKEND']).compact.uniq
|
53
|
-
|
54
44
|
FLD_SEP = '|'
|
55
45
|
IDX_REF = '^'
|
56
46
|
KEY_REF = '*'
|
57
47
|
SYS_KEY = '~'
|
58
48
|
|
59
|
-
|
49
|
+
IDX_REF_ESC = Regexp.escape(IDX_REF)
|
50
|
+
KEY_REF_ESC = Regexp.escape(KEY_REF)
|
51
|
+
|
52
|
+
INDEX_PATTERN = %r{\A#{IDX_REF_ESC}\d+\z}
|
53
|
+
|
54
|
+
BACKENDS = []
|
55
|
+
BACKEND_BY_EXT = {}
|
56
|
+
|
57
|
+
class << self
|
58
|
+
|
59
|
+
def register(klass, ext, prio = -1, meth = true)
|
60
|
+
BACKENDS.insert(prio, name = klass.name[/::(\w+)Store\z/, 1])
|
61
|
+
Array(ext).each { |i| BACKEND_BY_EXT[i.prepend('.')] = name }
|
62
|
+
|
63
|
+
klass.const_set(:EXT, ext)
|
64
|
+
klass.class_eval('def store_ext; EXT; end', __FILE__, __LINE__) if meth
|
65
|
+
end
|
66
|
+
|
67
|
+
def open(*args, &block)
|
68
|
+
new(*args).open(&block)
|
69
|
+
end
|
60
70
|
|
61
|
-
def self.open(*args, &block)
|
62
|
-
new(*args).open(&block)
|
63
71
|
end
|
64
72
|
|
73
|
+
attr_reader :backend
|
74
|
+
|
65
75
|
def initialize(id, lingo)
|
66
|
-
@config = lingo.database_config(id)
|
76
|
+
@id, @lingo, @config, @db = id, lingo, lingo.database_config(id), nil
|
67
77
|
|
68
|
-
@
|
69
|
-
@
|
70
|
-
@crypter = Crypter.new if @config.has_key?('crypt')
|
78
|
+
@srcfile = Lingo.find(:dict, @config['name'], relax: true)
|
79
|
+
@crypter = @config.has_key?('crypt') && Crypter.new
|
71
80
|
|
72
81
|
begin
|
73
|
-
@
|
74
|
-
FileUtils.mkdir_p(File.dirname(@
|
82
|
+
@stofile = Lingo.find(:store, @srcfile)
|
83
|
+
FileUtils.mkdir_p(File.dirname(@stofile))
|
84
|
+
rescue SourceFileNotFoundError => err
|
85
|
+
@stofile = skip_ext = err.id
|
86
|
+
backend = backend_from_file(@stofile) unless err.name
|
75
87
|
rescue NoWritableStoreError
|
76
|
-
|
88
|
+
backend = HashStore
|
77
89
|
end
|
78
90
|
|
79
|
-
|
80
|
-
|
81
|
-
@dbm_name << store_ext if respond_to?(:store_ext, true)
|
82
|
-
|
91
|
+
use_backend(backend, skip_ext)
|
83
92
|
init_cachable
|
84
|
-
convert unless uptodate?
|
85
|
-
end
|
86
93
|
|
87
|
-
|
88
|
-
@backend ||= BACKENDS.find { |mod|
|
89
|
-
break self.class.const_get("#{mod}Store") if Object.const_defined?(mod)
|
90
|
-
} || HashStore
|
94
|
+
convert unless uptodate?
|
91
95
|
end
|
92
96
|
|
93
97
|
def closed?
|
@@ -97,6 +101,8 @@ class Lingo
|
|
97
101
|
def open
|
98
102
|
@db = _open if closed?
|
99
103
|
block_given? ? yield(self) : self
|
104
|
+
rescue => err
|
105
|
+
raise DatabaseError.new(:open, @stofile, err)
|
100
106
|
ensure
|
101
107
|
close if @db && block_given?
|
102
108
|
end
|
@@ -134,16 +140,36 @@ class Lingo
|
|
134
140
|
val.uniq!
|
135
141
|
store(key, val)
|
136
142
|
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
_set(key, val)
|
143
|
+
arg = [key, val.join(FLD_SEP)]
|
144
|
+
_set(*@crypter ? @crypter.encode(*arg) : arg)
|
141
145
|
end
|
142
146
|
|
143
147
|
private
|
144
148
|
|
145
|
-
def
|
146
|
-
|
149
|
+
def use_backend(backend = nil, skip_ext = false)
|
150
|
+
[ENV['LINGO_BACKEND'], *BACKENDS].each { |mod|
|
151
|
+
backend = get_backend(mod) and break if mod
|
152
|
+
} unless backend
|
153
|
+
|
154
|
+
extend(@backend = backend || HashStore)
|
155
|
+
|
156
|
+
@stofile << store_ext if !skip_ext && respond_to?(:store_ext)
|
157
|
+
end
|
158
|
+
|
159
|
+
def get_backend(mod)
|
160
|
+
self.class.const_get("#{mod}Store") if Object.const_defined?(mod)
|
161
|
+
rescue TypeError, NameError
|
162
|
+
end
|
163
|
+
|
164
|
+
def backend_from_file(file)
|
165
|
+
ext = File.extname(file)
|
166
|
+
|
167
|
+
mod = BACKEND_BY_EXT[ext] or raise BackendNotFoundError.new(file)
|
168
|
+
get_backend(mod) or raise BackendNotAvailableError.new(mod, file)
|
169
|
+
end
|
170
|
+
|
171
|
+
def uptodate?(file = @stofile)
|
172
|
+
src = Pathname.new(@srcfile)
|
147
173
|
@source_key = lambda { [src.size, src.mtime].join(FLD_SEP) }
|
148
174
|
|
149
175
|
sys_key = open { @db[SYS_KEY] } if File.exist?(file)
|
@@ -160,7 +186,7 @@ class Lingo
|
|
160
186
|
end
|
161
187
|
|
162
188
|
def _clear
|
163
|
-
File.delete(@
|
189
|
+
File.delete(@stofile) if File.exist?(@stofile)
|
164
190
|
end
|
165
191
|
|
166
192
|
def _open
|
@@ -186,42 +212,35 @@ class Lingo
|
|
186
212
|
end
|
187
213
|
end
|
188
214
|
|
215
|
+
def warn(*msg)
|
216
|
+
@lingo.warn(*msg)
|
217
|
+
end
|
218
|
+
|
189
219
|
def convert(verbose = @lingo.config.stderr.tty?)
|
190
|
-
src = Source.get(@config.fetch('txt-format', '
|
220
|
+
src = Source.get(@config.fetch('txt-format', 'key_value'), @id, @lingo)
|
191
221
|
|
192
222
|
if lex = @config['use-lex']
|
193
|
-
a,
|
194
|
-
|
195
|
-
'mode' => @config['lex-mode']
|
196
|
-
}, @lingo], ' '
|
197
|
-
|
198
|
-
dic = Language::Dictionary.new(*a)
|
199
|
-
gra = Language::Grammar.new(*a)
|
200
|
-
|
201
|
-
block = lambda { |form|
|
202
|
-
res = dic.find_word(form)
|
203
|
-
|
204
|
-
if res.unknown?
|
205
|
-
res = gra.find_compositum(form)
|
206
|
-
com = res.compo_form
|
207
|
-
end
|
223
|
+
a = [{ 'source' => lex.split(SEP_RE), 'mode' => @config['lex-mode'] }, @lingo]
|
224
|
+
d, g = Language::Dictionary.new(*a), Language::Grammar.new(*a); a = nil
|
208
225
|
|
209
|
-
|
226
|
+
sep, block = ' ', lambda { |f|
|
227
|
+
(r = d.find_word(f)).unknown? &&
|
228
|
+
(c = (r = g.find_compound(f)).compo_form) ? c.form : r.norm
|
210
229
|
}
|
211
230
|
end
|
212
231
|
|
213
232
|
ShowProgress.new(self, src.size, verbose) { |progress| create {
|
214
233
|
src.each { |key, val|
|
215
|
-
progress[src.
|
234
|
+
progress[src.pos]
|
216
235
|
|
217
236
|
if key
|
218
237
|
key.chomp!('.')
|
219
238
|
|
220
|
-
if lex && key.include?(
|
221
|
-
k = key.split(
|
239
|
+
if lex && key.include?(sep)
|
240
|
+
k = key.split(sep).map!(&block).join(sep)
|
222
241
|
|
223
|
-
c = k.count(
|
224
|
-
self[k.split(
|
242
|
+
c = k.count(sep) + 1
|
243
|
+
self[k.split(sep)[0, 3].join(sep)] = ["#{KEY_REF}#{c}"] if c > 3
|
225
244
|
|
226
245
|
key, val = k, val.map { |v| v.start_with?('#') ? key + v : v }
|
227
246
|
end
|
@@ -237,3 +256,9 @@ class Lingo
|
|
237
256
|
end
|
238
257
|
|
239
258
|
end
|
259
|
+
|
260
|
+
# in order of priority
|
261
|
+
require_relative 'database/libcdb_store'
|
262
|
+
require_relative 'database/sdbm_store'
|
263
|
+
require_relative 'database/gdbm_store'
|
264
|
+
require_relative 'database/hash_store'
|
data/lib/lingo/error.rb
CHANGED
@@ -37,7 +37,49 @@ class Lingo
|
|
37
37
|
end
|
38
38
|
|
39
39
|
def to_s
|
40
|
-
'No writable store found in search path'
|
40
|
+
'No writable store found in search path.'
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
class BackendNotFoundError < LingoError
|
46
|
+
|
47
|
+
attr_reader :file
|
48
|
+
|
49
|
+
def initialize(file)
|
50
|
+
@file = file
|
51
|
+
end
|
52
|
+
|
53
|
+
def to_s
|
54
|
+
"No backend found for `#{file}'."
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
class BackendNotAvailableError < LingoError
|
60
|
+
|
61
|
+
attr_reader :mod, :file
|
62
|
+
|
63
|
+
def initialize(mod, file)
|
64
|
+
@mod, @file = mod, file
|
65
|
+
end
|
66
|
+
|
67
|
+
def to_s
|
68
|
+
"Backend not available `#{mod}' for `#{file}'."
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
|
73
|
+
class DatabaseError < LingoError
|
74
|
+
|
75
|
+
attr_reader :action, :file, :err
|
76
|
+
|
77
|
+
def initialize(action, file, err)
|
78
|
+
@action, @file, @err = action, file, err
|
79
|
+
end
|
80
|
+
|
81
|
+
def to_s
|
82
|
+
"An error occured when trying to #{action} `#{file}': #{err} (#{err.class})"
|
41
83
|
end
|
42
84
|
|
43
85
|
end
|
@@ -119,4 +161,18 @@ class Lingo
|
|
119
161
|
|
120
162
|
end
|
121
163
|
|
164
|
+
class NameNotFoundError < LingoError
|
165
|
+
|
166
|
+
attr_reader :klass, :name
|
167
|
+
|
168
|
+
def initialize(klass, name)
|
169
|
+
@klass, @name = klass, name
|
170
|
+
end
|
171
|
+
|
172
|
+
def to_s
|
173
|
+
"No such #{klass.name.split('::').last} type `#{name}'."
|
174
|
+
end
|
175
|
+
|
176
|
+
end
|
177
|
+
|
122
178
|
end
|
@@ -33,6 +33,12 @@ class Lingo
|
|
33
33
|
include Cachable
|
34
34
|
include Reportable
|
35
35
|
|
36
|
+
def self.open(*args)
|
37
|
+
yield dictionary = new(*args)
|
38
|
+
ensure
|
39
|
+
dictionary.close if dictionary
|
40
|
+
end
|
41
|
+
|
36
42
|
def initialize(config, lingo)
|
37
43
|
unless config.has_key?('source')
|
38
44
|
raise ArgumentError, 'Required parameter `source\' missing.'
|
@@ -43,32 +49,29 @@ class Lingo
|
|
43
49
|
|
44
50
|
@suffixes, @infixes = [], []
|
45
51
|
|
46
|
-
|
47
|
-
|
48
|
-
t.downcase!
|
52
|
+
Array(lingo.dictionary_config['suffix']).each { |t, s|
|
53
|
+
t.downcase!
|
49
54
|
|
50
|
-
|
51
|
-
su, ex = suf.split('/')
|
55
|
+
a = t == 'f' ? @infixes : @suffixes
|
52
56
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
}
|
57
|
+
s.split.each { |r|
|
58
|
+
f, e = r.split('/')
|
59
|
+
a << [/#{f}$/i, e || '*', t]
|
57
60
|
}
|
58
|
-
|
61
|
+
}
|
59
62
|
|
60
|
-
@
|
61
|
-
@
|
63
|
+
@src = config['source'].map { |src| lingo.lexical_hash(src) }
|
64
|
+
@all = config['mode'].nil? || config['mode'].downcase == 'all'
|
62
65
|
|
63
66
|
lingo.dictionaries << self
|
64
67
|
end
|
65
68
|
|
66
69
|
def close
|
67
|
-
@
|
70
|
+
@src.each(&:close)
|
68
71
|
end
|
69
72
|
|
70
73
|
def report
|
71
|
-
super.tap { |rep| @
|
74
|
+
super.tap { |rep| @src.each { |src| rep.update(src.report) } }
|
72
75
|
end
|
73
76
|
|
74
77
|
# _dic_.find_word( _aString_ ) -> _aNewWord_
|
@@ -95,11 +98,11 @@ class Lingo
|
|
95
98
|
lex = [obj] if lex.empty? && obj.unknown?
|
96
99
|
|
97
100
|
# multiworder optimization
|
98
|
-
ref = %r{\A#{
|
101
|
+
ref = %r{\A#{Database::KEY_REF_ESC}\d+}
|
99
102
|
|
100
103
|
lex.each_with_object([]) { |l, s|
|
101
104
|
next if l.attr == LA_SYNONYM
|
102
|
-
next if l.attr !=
|
105
|
+
next if l.attr != LA_COMPOUND && obj.attr == WA_COMPOUND
|
103
106
|
|
104
107
|
select(l.form).each { |y| s << y unless y =~ ref }
|
105
108
|
}
|
@@ -109,10 +112,10 @@ class Lingo
|
|
109
112
|
#
|
110
113
|
# Sucht alle Wörterbücher durch und gibt den ersten Treffer zurück (+mode = first+), oder alle Treffer (+mode = all+)
|
111
114
|
def select(str)
|
112
|
-
@
|
115
|
+
@src.each_with_object([]) { |src, lex|
|
113
116
|
l = src[str] or next
|
114
117
|
lex.concat(l)
|
115
|
-
break lex unless @
|
118
|
+
break lex unless @all
|
116
119
|
}.tap { |lex| lex.sort!; lex.uniq! }
|
117
120
|
end
|
118
121
|
|