Class: Lingo

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

Overview

#

Lingo – A full-featured automatic indexing system #

#

Copyright (C) 2005-2007 John Vorhauer # Copyright (C) 2007-2016 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: ArrayUtils, Ctl, Debug, Language, TextUtils, Version Classes: App, Attendee, BackendError, BackendNotAvailableError, BackendNotFoundError, BufferedAttendee, CLI, Call, Config, ConfigError, ConfigLoadError, Database, DatabaseError, DeferredAttendee, FileError, FileExistsError, FileNotFoundError, Filter, InvalidDatabaseConfigError, LibraryLoadError, LingoError, MissingConfigError, NameNotFoundError, NoDatabaseConfigError, NoWritableStoreError, Progress, SourceFileNotFoundError, Srv, StoreError, 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'  }
}
ENCODING =

Default encoding

'UTF-8'.freeze
SEP_RE =
%r{[; ,|]}
VERSION =
Version.to_s

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(*args) ⇒ Lingo



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

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

  @config_args = args
  reset(false)
end

Instance Attribute Details

#dictionariesObject (readonly)

Returns the value of attribute dictionaries



239
240
241
# File 'lib/lingo.rb', line 239

def dictionaries
  @dictionaries
end

Class Method Details

.append_path(*path) ⇒ Object



124
125
126
# File 'lib/lingo.rb', line 124

def append_path(*path)
  include_path(path)
end

.basename(type, file) ⇒ Object



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

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

.basepath(type, file) ⇒ Object



120
121
122
# File 'lib/lingo.rb', line 120

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

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



80
81
82
# File 'lib/lingo.rb', line 80

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

.CLI(args, extra = nil, &block) ⇒ Object



80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/lingo/cli.rb', line 80

def self.CLI(args, extra = nil, &block)
  opt, req = args.partition { |arg| arg.sub!(/\?\z/, '') }

  unless (n = ARGV.size - req.size) >= 0 && n <= opt.size
    msg = "Usage: #{$0}#{args.map { |arg| [' ', arg].zip(
      opt.include?(arg) ? %w[[ ]] : %w[< >]).join }.join}"

    abort Array(extra).unshift(msg).join("\n\n")
  end

  Object.new.extend(TextUtils).instance_eval(&block)
rescue LingoError => err
  abort err.to_s
ensure
  ObjectSpace.each_object(Zlib::GzipWriter, &:close)
end

.ctlObject



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

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

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



100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/lingo.rb', line 100

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



132
133
134
135
136
# File 'lib/lingo.rb', line 132

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

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



84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/lingo.rb', line 84

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



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

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

.talk(*args) ⇒ Object



76
77
78
# File 'lib/lingo.rb', line 76

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

Instance Method Details

#attendees(arg = Object) ⇒ Object



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

def attendees(arg = Object)
  @attendees.grep(arg.is_a?(Class) ? arg :
    Attendee.const_get(arg.to_s.camelcase))
end

#configObject



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

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

#database_config(id) ⇒ Object



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

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



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

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

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



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
300
301
302
303
304
# File 'lib/lingo.rb', line 273

def invite(list = config['meeting/attendees'])
  supplier, subscriber = Hash.array, Hash.array

  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



258
259
260
# File 'lib/lingo.rb', line 258

def lexical_hash(src)
  @lexical_hash[src]
end

#reset(close = true) ⇒ Object



315
316
317
318
319
# File 'lib/lingo.rb', line 315

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



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

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

#talkObject



262
263
264
265
266
267
268
269
270
271
# File 'lib/lingo.rb', line 262

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

  Debug.ps(:lingo_talk)
ensure
  reset
end

#warn(*msg) ⇒ Object



321
322
323
# File 'lib/lingo.rb', line 321

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