lingo 1.8.1 → 1.8.2
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/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
|
|