class Lingo

Constants

BASE

The system-wide Lingo directory (LINGO_BASE).

CURR

The local Lingo directory (LINGO_CURR).

ENC

Default encoding

FIND_OPTIONS

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

HOME

The user’s personal Lingo directory (LINGO_HOME).

PATH

The search path for Lingo dictionary and configuration files.

SEP_RE
VERSION

Attributes

dictionaries[R]
report_status[R]
report_time[R]

Public Class Methods

append_path(*path) click to toggle source
# File lib/lingo.rb, line 115
def append_path(*path)
  include_path(path)
end
basename(type, file) click to toggle source
# File lib/lingo.rb, line 106
def basename(type, file)
  dir, name = File.split(file)
  type != :dict ? name : File.join(File.basename(dir), name)
end
basepath(type, file) click to toggle source
# File lib/lingo.rb, line 111
def basepath(type, file)
  File.join(options_for(type)[:dir], basename(type, file))
end
call(cfg = find(:config, 'lingo-call'), args = [], &block) click to toggle source
# File lib/lingo.rb, line 72
def call(cfg = find(:config, 'lingo-call'), args = [], &block)
  Call.new(['-c', cfg, *args]).call(&block)
end
ctl() click to toggle source
# File lib/lingo/ctl.rb, line 230
def self.ctl
  Ctl.ctl
rescue => err
  raise if $VERBOSE
  abort "#{err.backtrace.first}: #{err} (#{err.class})"
end
find(type, file, options = {}) { |err| ... } click to toggle source
# File lib/lingo.rb, line 91
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) click to toggle source
# File lib/lingo.rb, line 123
def get_const(name, klass = self)
  klass.const_get(name.camelcase)
rescue NameError
  raise NameNotFoundError.new(klass, name)
end
list(type, options = {}) click to toggle source
# File lib/lingo.rb, line 76
def list(type, options = {})
  options = options_for(type, options)
  path    = path_for(options)

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

  [].tap { |list| walk(path, options) { |dir|
    Dir[File.join(dir, glob)].sort!.each { |file|
      pn = Pathname.new(file)
      list << realpath_for(pn, path) if pn.file?
    }
  } }
end
new(*args) click to toggle source
# File lib/lingo.rb, line 227
def initialize(*args)
  @config_args = args
  reset(false)
end
prepend_path(*path) click to toggle source
# File lib/lingo.rb, line 119
def prepend_path(*path)
  include_path(path, true)
end
talk(*args) click to toggle source
# File lib/lingo.rb, line 68
def talk(*args)
  new(*args).talk
end

Private Class Methods

file_with_ext(file, options) click to toggle source
# File lib/lingo.rb, line 196
def file_with_ext(file, options)
  ext = options[:ext]
  ext && File.extname(file).empty? ? "#{file}.#{ext}" : file
end
find_file(file, path, options) click to toggle source
# File lib/lingo.rb, line 135
def find_file(file, path, options)
  if glob = options[:glob]
    file = File.chomp_ext(file)
    options[:ext] ||= '*'
  end

  file = file_with_ext(file, options)
  pn   = Pathname.new(file).cleanpath

  if pn.relative?
    walk(path, options) { |dir|
      pn2 = pn.expand_path(dir)
      ex  = pn2.exist?

      pn2 = Pathname.glob(pn2).first if glob && !ex
      pn  = pn2 and break if glob ? pn2 : ex
    }
  end

  realpath_for(pn, path)
rescue Errno::ENOENT
  raise unless relax = options[:relax]
  relax.respond_to?(:[]) ? relax[file] : file
end
find_store(file, path, options) click to toggle source
# File lib/lingo.rb, line 160
def find_store(file, path, options)
  base = basename(:dict, find(:dict, file, path) {
    raise SourceFileNotFoundError.new(nil, find_file(file, path,
      options.merge(glob: true, relax: lambda { |_file|
        raise SourceFileNotFoundError.new(file, _file)
      })
    ))
  })

  walk(path.reverse, options, false) { |dir|
    Pathname.new(dir).ascend { |i|
      begin
        stat = i.stat

        break true if stat.file? || !stat.writable?
        return File.chomp_ext(File.join(dir, base))
      rescue Errno::ENOENT
      end
    }
  }

  raise NoWritableStoreError.new(file, path)
end
include_path(path, pre = false) click to toggle source
# File lib/lingo.rb, line 131
def include_path(path, pre = false)
  PATH.insert(pre ? 0 : -1, *path.map!(&:to_s))
end
options_for(type, options = {}) click to toggle source
# File lib/lingo.rb, line 184
def options_for(type, options = {})
  if find_options = FIND_OPTIONS[type]
    options = find_options.merge(options)
  else
    raise ArgumentError, "Invalid type `#{type.inspect}'", caller(1)
  end
end
path_for(options) click to toggle source
# File lib/lingo.rb, line 192
def path_for(options)
  options[:path] || PATH
end
realpath_for(pn, path) click to toggle source
# File lib/lingo.rb, line 214
def realpath_for(pn, path)
  pn.realpath(path.first).to_s
end
require_optional(lib) click to toggle source
# File lib/lingo.rb, line 218
def require_optional(lib)
  require lib unless ENV["LINGO_NO_#{lib.upcase}"]
rescue LoadError
end
walk(path, options, legacy = true) { |join| ... } click to toggle source
# File lib/lingo.rb, line 201
def walk(path, options, legacy = true)
  dirs = [options[:dir].to_s]
  dirs << '' if legacy
  dirs.uniq!

  seen = Hash.new { |h, k| h[k] = true; false }

  path.each { |d|
    next if seen[d = File.expand_path(d)]
    dirs.each { |i| yield File.join(d, i) } or break
  }
end

Public Instance Methods

config() click to toggle source
# File lib/lingo.rb, line 232
def config
  @config ||= Config.new(*@config_args)
end
database_config(id) click to toggle source
# File lib/lingo.rb, line 242
def database_config(id)
  dictionary_config['databases'][id].tap { |cfg|
    raise NoDatabaseConfigError.new(id) unless cfg
    raise InvalidDatabaseConfigError.new(id) unless cfg.has_key?('name')
  }
end
dictionary_config() click to toggle source
# File lib/lingo.rb, line 236
def dictionary_config
  @dictionary_config ||= config['language/dictionary']
rescue => err
  raise ConfigLoadError.new(err)
end
invite(list = config['meeting/attendees']) click to toggle source
# File lib/lingo.rb, line 260
def invite(list = config['meeting/attendees'])
  supplier   = Hash.new { |h, k| h[k] = [] }
  subscriber = Hash.new { |h, k| h[k] = [] }

  last_link, auto_link = '', 0

  list.each { |hash|
    # {'attendee' => {'name'=>'Attendee', 'in'=>'nase', 'out'=>'ohr', 'param'=>'hase'}}

    cfg = hash.values.first.merge('name' => name = hash.keys.first.camelcase)

    %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']

    cfg.update(config["language/attendees/#{name.downcase}"] || {})

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

    { '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.add_subscriber(subscriber[ch])
  } }
end
lexical_hash(src) click to toggle source
# File lib/lingo.rb, line 249
def lexical_hash(src)
  @lexical_hash[src]
end
reset(close = true) click to toggle source
# File lib/lingo.rb, line 304
def reset(close = true)
  dictionaries.each(&:close) if close
  @dictionaries, @attendees = [], []
  @lexical_hash = Hash.new { |h, k| h[k] = Language::LexicalHash.new(k, self) }
end
start(report_status = config['status'], report_time = config['perfmon']) click to toggle source
# File lib/lingo.rb, line 290
def start(report_status = config['status'], report_time = config['perfmon'])
  @report_status, @report_time = report_status, report_time

  time = Benchmark.realtime {
    @attendees.first.listen(AgendaItem.new(Attendee::STR_CMD_TALK))
  }

  if report_status || report_time
    warn "Require protocol...\n#{separator = '-' * 61}"
    @attendees.first.listen(AgendaItem.new(Attendee::STR_CMD_STATUS))
    warn "#{separator}\nThe duration of the meeting was #{time.to_hms(2)}"
  end
end
talk() click to toggle source
# File lib/lingo.rb, line 253
def talk
  invite
  start
ensure
  reset
end
warn(*msg) click to toggle source
# File lib/lingo.rb, line 310
def warn(*msg)
  config.stderr.puts(*msg)
end