lingo 1.8.1 → 1.8.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (99) hide show
  1. data/ChangeLog +23 -5
  2. data/README +1 -1
  3. data/Rakefile +5 -7
  4. data/TODO +2 -0
  5. data/bin/lingo +5 -1
  6. data/de.lang +1 -1
  7. data/en/lingo-syn.txt +0 -0
  8. data/en.lang +2 -1
  9. data/lib/lingo/attendee/abbreviator.rb +8 -9
  10. data/lib/lingo/attendee/debugger.rb +5 -4
  11. data/lib/lingo/attendee/decomposer.rb +8 -3
  12. data/lib/lingo/attendee/dehyphenizer.rb +19 -63
  13. data/lib/lingo/attendee/formatter.rb +1 -1
  14. data/lib/lingo/attendee/multi_worder.rb +67 -155
  15. data/lib/lingo/attendee/noneword_filter.rb +16 -9
  16. data/lib/lingo/attendee/object_filter.rb +1 -1
  17. data/lib/lingo/attendee/sequencer.rb +32 -63
  18. data/lib/lingo/attendee/stemmer/porter.rb +343 -0
  19. data/{info/gpl-hdr.txt → lib/lingo/attendee/stemmer.rb} +33 -0
  20. data/lib/lingo/attendee/synonymer.rb +10 -9
  21. data/lib/lingo/attendee/text_reader.rb +102 -76
  22. data/lib/lingo/attendee/text_writer.rb +23 -26
  23. data/lib/lingo/attendee/tokenizer.rb +13 -27
  24. data/lib/lingo/attendee/variator.rb +26 -66
  25. data/lib/lingo/attendee/vector_filter.rb +42 -43
  26. data/lib/lingo/attendee/word_searcher.rb +6 -7
  27. data/lib/lingo/attendee.rb +25 -7
  28. data/lib/lingo/buffered_attendee.rb +36 -10
  29. data/lib/lingo/cachable.rb +8 -8
  30. data/lib/lingo/config.rb +5 -6
  31. data/lib/lingo/ctl.rb +2 -3
  32. data/lib/lingo/database/crypter.rb +9 -26
  33. data/lib/lingo/database/gdbm_store.rb +3 -5
  34. data/lib/lingo/database/libcdb_store.rb +4 -6
  35. data/lib/lingo/database/sdbm_store.rb +11 -6
  36. data/lib/lingo/database/show_progress.rb +3 -43
  37. data/lib/lingo/database/source/key_value.rb +2 -6
  38. data/lib/lingo/database/source/multi_key.rb +3 -5
  39. data/lib/lingo/database/source/multi_value.rb +2 -6
  40. data/lib/lingo/database/source/single_word.rb +4 -6
  41. data/lib/lingo/database/source/word_class.rb +4 -10
  42. data/lib/lingo/database/source.rb +20 -18
  43. data/lib/lingo/database.rb +84 -59
  44. data/lib/lingo/error.rb +57 -1
  45. data/lib/lingo/language/dictionary.rb +21 -18
  46. data/lib/lingo/language/grammar.rb +40 -49
  47. data/lib/lingo/language/lexical.rb +6 -6
  48. data/lib/lingo/language/lexical_hash.rb +6 -0
  49. data/lib/lingo/language/word.rb +32 -15
  50. data/lib/lingo/language/word_form.rb +1 -1
  51. data/lib/lingo/language.rb +14 -25
  52. data/lib/lingo/reportable.rb +12 -10
  53. data/lib/lingo/show_progress.rb +81 -0
  54. data/lib/lingo/version.rb +1 -1
  55. data/lib/lingo.rb +63 -24
  56. data/lingo-call.cfg +6 -10
  57. data/lingo.cfg +60 -44
  58. data/lir.cfg +42 -41
  59. data/test/attendee/ts_abbreviator.rb +3 -5
  60. data/test/attendee/ts_decomposer.rb +3 -5
  61. data/test/attendee/ts_multi_worder.rb +87 -145
  62. data/test/attendee/ts_noneword_filter.rb +5 -3
  63. data/test/attendee/ts_object_filter.rb +5 -3
  64. data/test/attendee/ts_sequencer.rb +3 -5
  65. data/test/attendee/ts_stemmer.rb +309 -0
  66. data/test/attendee/ts_synonymer.rb +15 -11
  67. data/test/attendee/ts_text_reader.rb +12 -15
  68. data/test/attendee/ts_text_writer.rb +24 -29
  69. data/test/attendee/ts_tokenizer.rb +9 -7
  70. data/test/attendee/ts_variator.rb +4 -4
  71. data/test/attendee/ts_vector_filter.rb +24 -16
  72. data/test/attendee/ts_word_searcher.rb +20 -36
  73. data/test/{lir.csv → lir.vec} +0 -0
  74. data/test/ref/artikel.vec +943 -943
  75. data/test/ref/artikel.ven +943 -943
  76. data/test/ref/lir.non +201 -201
  77. data/test/ref/lir.seq +178 -178
  78. data/test/ref/lir.syn +49 -49
  79. data/test/ref/lir.vec +329 -0
  80. data/test/test_helper.rb +20 -36
  81. data/test/ts_database.rb +10 -10
  82. data/test/ts_language.rb +279 -319
  83. metadata +93 -104
  84. data/info/Objekte.png +0 -0
  85. data/info/Typen.png +0 -0
  86. data/info/database.png +0 -0
  87. data/info/db_small.png +0 -0
  88. data/info/download.png +0 -0
  89. data/info/kerze.png +0 -0
  90. data/info/language.png +0 -0
  91. data/info/lingo.png +0 -0
  92. data/info/logo.png +0 -0
  93. data/info/meeting.png +0 -0
  94. data/info/types.png +0 -0
  95. data/lingo-all.cfg +0 -89
  96. data/porter/stem.cfg +0 -311
  97. data/porter/stem.rb +0 -150
  98. data/test/ref/lir.csv +0 -329
  99. data/test.cfg +0 -79
@@ -38,17 +38,15 @@ class Lingo
38
38
 
39
39
  def initialize(id, lingo)
40
40
  super
41
-
42
- @wc = @config.fetch('def-wc', 's').downcase
43
- @mul_wc = @config.fetch('def-mul-wc', @wc).downcase
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/ ? @mul_wc : @wc}]]
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, valstr = key.strip, val.strip
50
- val = valstr.gsub(/\s+#/, '#').scan(/\S.+?\s*#\w/)
51
- val = val.map do |str|
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
- const_get(name.camelcase).new(*args)
69
+ Lingo.get_const(name, self).new(*args)
69
70
  end
70
71
 
71
- attr_reader :position
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
- @pn_source = Pathname.new(source_file)
83
- @pn_reject = Pathname.new(reject_file) if reject_file
84
+ @src = Pathname.new(source_file)
85
+ @rej = Pathname.new(reject_file) if reject_file
84
86
 
85
- raise SourceFileNotFoundError.new(name, id) unless @pn_source.exist?
87
+ raise SourceFileNotFoundError.new(name, id) unless @src.exist?
86
88
 
87
- @wordclass = @config.fetch('def-wc', '?').downcase
88
- @separator = @config['separator']
89
+ @def = @config.fetch('def-wc', Language::LA_UNKNOWN).downcase
90
+ @sep = @config['separator']
89
91
 
90
- @legal_word = '(?:' + PRINTABLE_CHAR + '|[' + Regexp.escape('- /&()[].,') + '])+' # TODO: v1.60 - ',' bei Source zulassen; in const.rb einbauen
91
- @line_pattern = Regexp.new('^'+@legal_word+'$')
92
+ @wrd = "(?:#{PRINTABLE_CHAR}|#{LEGAL_CHAR})+"
93
+ @pat = /^#{@wrd}$/
92
94
 
93
- @position = 0
95
+ @pos = 0
94
96
  end
95
97
 
96
98
  def size
97
- @pn_source.size
99
+ @src.size
98
100
  end
99
101
 
100
102
  def each
101
- reject_file = @pn_reject.open('w', encoding: ENC) if @pn_reject
103
+ reject_file = @rej.open('w', encoding: ENC) if @rej
102
104
 
103
- @pn_source.each_line($/, encoding: ENC) { |line|
104
- @position += length = line.bytesize
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 =~ @line_pattern
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
- @pn_reject.delete if @pn_reject.size == 0
124
+ @rej.delete if @rej.size == 0
123
125
  end
124
126
  end
125
127
 
@@ -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
- INDEX_PATTERN = %r{\A#{Regexp.escape(IDX_REF)}\d+\z}
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
- @id, @lingo = id, lingo
69
- @src_file = Lingo.find(:dict, @config['name'])
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
- @dbm_name = Lingo.find(:store, @src_file)
74
- FileUtils.mkdir_p(File.dirname(@dbm_name))
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
- @backend = HashStore
88
+ backend = HashStore
77
89
  end
78
90
 
79
- extend(backend)
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
- def backend
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
- val = val.join(FLD_SEP)
138
- key, val = @crypter.encode(key, val) if @crypter
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 uptodate?(file = @dbm_name)
146
- src = Pathname.new(@src_file)
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(@dbm_name) if File.exist?(@dbm_name)
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', 'KeyValue'), @id, @lingo)
220
+ src = Source.get(@config.fetch('txt-format', 'key_value'), @id, @lingo)
191
221
 
192
222
  if lex = @config['use-lex']
193
- a, s = [{
194
- 'source' => lex.split(STRING_SEPARATOR_RE),
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
- com ? com.form : res.norm
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.position]
234
+ progress[src.pos]
216
235
 
217
236
  if key
218
237
  key.chomp!('.')
219
238
 
220
- if lex && key.include?(s)
221
- k = key.split(s).map!(&block).join(s)
239
+ if lex && key.include?(sep)
240
+ k = key.split(sep).map!(&block).join(sep)
222
241
 
223
- c = k.count(s) + 1
224
- self[k.split(s)[0, 3].join(s)] = ["#{KEY_REF}#{c}"] if c > 3
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
- if suffix = lingo.dictionary_config['suffix']
47
- suffix.each { |t, s|
48
- t.downcase!
52
+ Array(lingo.dictionary_config['suffix']).each { |t, s|
53
+ t.downcase!
49
54
 
50
- s.split.each { |suf|
51
- su, ex = suf.split('/')
55
+ a = t == 'f' ? @infixes : @suffixes
52
56
 
53
- (t == 'f' ? @infixes : @suffixes) << [
54
- Regexp.new(su << '$', 'i'), ex || '*', t
55
- ]
56
- }
57
+ s.split.each { |r|
58
+ f, e = r.split('/')
59
+ a << [/#{f}$/i, e || '*', t]
57
60
  }
58
- end
61
+ }
59
62
 
60
- @sources = config['source'].map { |src| lingo.lexical_hash(src) }
61
- @all_sources = config['mode'].nil? || config['mode'].downcase == 'all'
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
- @sources.each(&:close)
70
+ @src.each(&:close)
68
71
  end
69
72
 
70
73
  def report
71
- super.tap { |rep| @sources.each { |src| rep.update(src.report) } }
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#{Regexp.escape(Database::KEY_REF)}\d+}o
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 != LA_KOMPOSITUM && obj.attr == WA_KOMPOSITUM
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
- @sources.each_with_object([]) { |src, lex|
115
+ @src.each_with_object([]) { |src, lex|
113
116
  l = src[str] or next
114
117
  lex.concat(l)
115
- break lex unless @all_sources
118
+ break lex unless @all
116
119
  }.tap { |lex| lex.sort!; lex.uniq! }
117
120
  end
118
121