Class: Lingo

Inherits:
Object
  • Object
show all
Defined in:
lib/lingo/call.rb,
lib/lingo.rb,
lib/lingo/srv.rb,
lib/lingo/cli.rb,
lib/lingo/ctl.rb,
lib/lingo/app.rb,
lib/lingo/web.rb,
lib/lingo/error.rb,
lib/lingo/debug.rb,
lib/lingo/config.rb,
lib/lingo/version.rb,
lib/lingo/progress.rb,
lib/lingo/language.rb,
lib/lingo/attendee.rb,
lib/lingo/database.rb,
lib/lingo/language/char.rb,
lib/lingo/language/word.rb,
lib/lingo/language/token.rb,
lib/lingo/database/source.rb,
lib/lingo/database/crypter.rb,
lib/lingo/attendee/stemmer.rb,
lib/lingo/language/lexical.rb,
lib/lingo/language/grammar.rb,
lib/lingo/attendee/debugger.rb,
lib/lingo/buffered_attendee.rb,
lib/lingo/deferred_attendee.rb,
lib/lingo/database/progress.rb,
lib/lingo/attendee/variator.rb,
lib/lingo/language/word_form.rb,
lib/lingo/attendee/synonymer.rb,
lib/lingo/attendee/formatter.rb,
lib/lingo/attendee/tokenizer.rb,
lib/lingo/attendee/sequencer.rb,
lib/lingo/attendee/decomposer.rb,
lib/lingo/database/sdbm_store.rb,
lib/lingo/database/hash_store.rb,
lib/lingo/database/gdbm_store.rb,
lib/lingo/language/dictionary.rb,
lib/lingo/attendee/text_writer.rb,
lib/lingo/attendee/text_reader.rb,
lib/lingo/attendee/abbreviator.rb,
lib/lingo/attendee/dehyphenizer.rb,
lib/lingo/language/lexical_hash.rb,
lib/lingo/database/libcdb_store.rb,
lib/lingo/attendee/multi_worder.rb,
lib/lingo/attendee/object_filter.rb,
lib/lingo/attendee/vector_filter.rb,
lib/lingo/attendee/word_searcher.rb,
lib/lingo/attendee/stemmer/porter.rb,
lib/lingo/attendee/noneword_filter.rb,
lib/lingo/database/source/multi_key.rb,
lib/lingo/database/source/key_value.rb,
lib/lingo/database/source/word_class.rb,
lib/lingo/database/source/multi_value.rb,
lib/lingo/database/source/single_word.rb

Overview

#

Lingo – A full-featured automatic indexing system #

#

Copyright (C) 2005-2007 John Vorhauer # Copyright (C) 2007-2014 John Vorhauer, Jens Wille #

#

Lingo is free software; you can redistribute it and/or modify it under the # terms of the GNU Affero General Public License as published by the Free # Software Foundation; either version 3 of the License, or (at your option) # any later version. #

#

Lingo is distributed in the hope that it will be useful, but WITHOUT ANY # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for # more details. #

#

You should have received a copy of the GNU Affero General Public License # along with Lingo. If not, see <www.gnu.org/licenses/>. #

#

++

Direct Known Subclasses

Call

Defined Under Namespace

Modules: Ctl, Debug, Language, Version Classes: App, Attendee, BackendNotAvailableError, BackendNotFoundError, BufferedAttendee, CLI, Call, Config, ConfigError, ConfigLoadError, Database, DatabaseError, DeferredAttendee, FileNotFoundError, InvalidDatabaseConfigError, LibraryLoadError, LingoError, MissingConfigError, NameNotFoundError, NoDatabaseConfigError, NoWritableStoreError, Progress, SourceFileNotFoundError, Srv, TokenizeError, Web

Constant Summary

BASE =

The system-wide Lingo directory (LINGO_BASE).

ENV['LINGO_BASE'] || File.expand_path('../..', __FILE__)
HOME =

The user's personal Lingo directory (LINGO_HOME).

ENV['LINGO_HOME'] || File.join(ENV.user_home, '.lingo')
CURR =

The local Lingo directory (LINGO_CURR).

ENV['LINGO_CURR'] || '.'
PATH =

The search path for Lingo dictionary and configuration files.

ENV['LINGO_PATH'].nil? ? [CURR, HOME, BASE] :
ENV['LINGO_PATH'].split(File::PATH_SEPARATOR)
FIND_OPTIONS =

Map of file types to their standard location and file extension.

{
  config: { dir: 'config', ext: 'cfg'  },
  dict:   { dir: 'dict',   ext: 'txt'  },
  lang:   { dir: 'lang',   ext: 'lang' },
  store:  { dir: 'store',  ext:  nil   },
  sample: { dir: 'txt',    ext: 'txt'  }
}
SEP_RE =
%r{[; ,|]}
VERSION =
Version.to_s

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(*args) ⇒ Lingo

Returns a new instance of Lingo



226
227
228
229
230
231
# File 'lib/lingo.rb', line 226

def initialize(*args)
  Debug.ps(:lingo_new)

  @config_args = args
  reset(false)
end

Instance Attribute Details

#dictionariesObject (readonly)

Returns the value of attribute dictionaries



233
234
235
# File 'lib/lingo.rb', line 233

def dictionaries
  @dictionaries
end

Class Method Details

.append_path(*path) ⇒ Object



118
119
120
# File 'lib/lingo.rb', line 118

def append_path(*path)
  include_path(path)
end

.basename(type, file) ⇒ Object



109
110
111
112
# File 'lib/lingo.rb', line 109

def basename(type, file)
  dir, name = File.split(file)
  type != :dict ? name : File.join(File.basename(dir), name)
end

.basepath(type, file) ⇒ Object



114
115
116
# File 'lib/lingo.rb', line 114

def basepath(type, file)
  File.join(options_for(type)[:dir], basename(type, file))
end

.call(cfg = find(:config, 'lingo-call'), args = [], &block) ⇒ Object



74
75
76
# File 'lib/lingo.rb', line 74

def call(cfg = find(:config, 'lingo-call'), args = [], &block)
  Call.new(['-c', cfg, *args]).call(&block)
end

.ctlObject



296
297
298
299
300
301
# File 'lib/lingo/ctl.rb', line 296

def self.ctl
  Ctl.ctl
rescue => err
  raise if $VERBOSE
  abort "#{err.backtrace.first}: #{err} (#{err.class})"
end

.find(type, file, options = {}) ⇒ Object



94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/lingo.rb', line 94

def find(type, file, options = {})
  if options.is_a?(Array)
    path    = options
    options = options_for(type)
  else
    options = options_for(type, options)
    path    = path_for(options)
  end

  type = :file if type != :store
  send("find_#{type}", file, path, options)
rescue RuntimeError, Errno::ENOENT => err
  block_given? ? yield(err) : raise
end

.get_const(name, klass = self) ⇒ Object



126
127
128
129
130
# File 'lib/lingo.rb', line 126

def get_const(name, klass = self)
  klass.const_get(name.camelcase)
rescue NameError
  raise NameNotFoundError.new(klass, name)
end

.list(type, options = {}) ⇒ Object



78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/lingo.rb', line 78

def list(type, options = {})
  options = options_for(type, options)

  glob, list = file_with_ext('*', options), []
  glob = File.join('??', glob) if type == :dict

  walk(path = path_for(options), options) { |dir|
    Dir[File.join(dir, glob)].sort!.each { |file|
      pn = Pathname.new(file)
      list << realpath_for(pn, path) if pn.file?
    }
  }

  list
end

.prepend_path(*path) ⇒ Object



122
123
124
# File 'lib/lingo.rb', line 122

def prepend_path(*path)
  include_path(path, true)
end

.talk(*args) ⇒ Object



70
71
72
# File 'lib/lingo.rb', line 70

def talk(*args)
  new(*args).talk
end

Instance Method Details

#configObject



235
236
237
238
239
# File 'lib/lingo.rb', line 235

def config
  @config ||= Config.new(*@config_args)
rescue => err
  raise ConfigLoadError.new(err)
end

#database_config(id) ⇒ Object



245
246
247
248
249
250
# File 'lib/lingo.rb', line 245

def database_config(id)
  dictionary_config['databases'][id].tap { |cfg|
    raise NoDatabaseConfigError.new(id) unless cfg
    raise InvalidDatabaseConfigError.new(id) unless cfg.key?('name')
  }
end

#dictionary_configObject



241
242
243
# File 'lib/lingo.rb', line 241

def dictionary_config
  @dictionary_config ||= config['language/dictionary']
end

#invite(list = config['meeting/attendees']) ⇒ Object



267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
# File 'lib/lingo.rb', line 267

def invite(list = config['meeting/attendees'])
  supplier   = Hash.nest { [] }
  subscriber = Hash.nest { [] }

  last_link, auto_link = '', 0

  list.each { |hash|
    name = (name_key = hash.keys.first).camelcase

    cfg = (config["language/attendees/#{name.downcase}"] || {})
      .merge(hash.values.first).update('name' => name)

    %w[in out].each { |key| (cfg[key] ||= '').downcase! }

    cfg['in']  = last_link                     if cfg['in'].empty?
    cfg['out'] = "auto_link-#{auto_link += 1}" if cfg['out'].empty?
    last_link  = cfg['out']

    @attendees << attendee = Attendee.const_get(name).new(cfg, self)

    unless name == (real = attendee.class.name.split('::').last)
      config.deprecate(name_key, real.underscore, attendee, :name)
    end

    { 'in' => subscriber, 'out' => supplier }.each { |key, target|
      cfg[key].split(SEP_RE).each { |ch| target[ch] << attendee }
    }
  }

  supplier.each { |ch, attendees| attendees.each { |att|
    att.subscribers.concat(subscriber[ch])
  } }
end

#lexical_hash(src) ⇒ Object



252
253
254
# File 'lib/lingo.rb', line 252

def lexical_hash(src)
  @lexical_hash[src]
end

#reset(close = true) ⇒ Object



305
306
307
308
309
# File 'lib/lingo.rb', line 305

def reset(close = true)
  dictionaries.each { |i| i.close } if close
  @dictionaries, @attendees = [], []
  @lexical_hash = Hash.nest { |k| Language::LexicalHash.new(k, self) }
end

#startObject



301
302
303
# File 'lib/lingo.rb', line 301

def start
  @attendees.first.control(:TALK)
end

#talkObject



256
257
258
259
260
261
262
263
264
265
# File 'lib/lingo.rb', line 256

def talk
  Debug.profile(config['profile']) {
    invite
    start
  }

  Debug.ps(:lingo_talk)
ensure
  reset
end

#warn(*msg) ⇒ Object



311
312
313
# File 'lib/lingo.rb', line 311

def warn(*msg)
  config.warn(*msg)
end