# -*- coding: utf-8 -*-
#
# Copyright (C) 2011 Miho SUZUKI
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
require 'thor'
require 'rainbow'
require 'pathname'
require "logaling/repository"
require "logaling/project"
require "logaling/glossary"
require "logaling/glossary_source"
require "logaling/config"
module Logaling::Command
LOGALING_CONFIG = '.logaling'
class Application < Thor
def initialize(*args)
super
@logaling_home = options["logaling-home"] ? options["logaling-home"] : LOGALING_HOME
@repository = Logaling::Repository.new(@logaling_home)
@config = Logaling::Config.load(@repository.config_path)
@dotfile_path = options["logaling-config"] ? options["logaling-config"] : Logaling::Project.find_dotfile
@project_config_path = File.join(@dotfile_path, 'config')
@config.load(@project_config_path)
rescue Logaling::ProjectNotFound => e
@project_config_path = nil
ensure
@config.merge!(options)
end
map '-a' => :add,
'-d' => :delete,
'-u' => :update,
'-l' => :lookup,
'-i' => :import,
'-n' => :new,
'-r' => :register,
'-U' => :unregister,
'-L' => :list,
'-s' => :show,
'-v' => :version,
'-c' => :config,
'-C' => :copy
class_option "glossary", type: :string, aliases: "-g"
class_option "source-language", type: :string, aliases: "-S"
class_option "target-language", type: :string, aliases: "-T"
class_option "logaling-home", type: :string, aliases: "-h"
class_option "logaling-config", type: :string, aliases: "-c"
desc 'new [PROJECT NAME] [SOURCE LANGUAGE] [TARGET LANGUAGE(optional)]', 'Create .logaling'
method_option "no-register", type: :boolean, default: false
method_option "personal", type: :boolean, default: false
def new(project_name, source_language, target_language=nil)
unless options['personal']
unless File.exist?(logaling_config_path)
FileUtils.mkdir_p(File.join(logaling_config_path, "glossary"))
config = Logaling::Config.new("glossary" => project_name, "source-language" => source_language)
config.merge!("target-language" => target_language) if target_language
config.save(File.join(logaling_config_path, "config"))
unless options["no-register"]
@dotfile_path = options["logaling-config"] || Logaling::Project.find_dotfile
@project_config_path = File.join(@dotfile_path, 'config')
@config.load(@project_config_path)
register_and_index
end
say "Successfully created #{logaling_config_path}"
else
say "#{logaling_config_path} already exists."
end
else
raise Logaling::CommandFailed, "[TARGET-LANGUAGE] is required when you use '--personal'" unless target_language
personal_project = @repository.create_personal_project(project_name, source_language, target_language)
say "Successfully created #{personal_project.path}"
end
rescue Logaling::CommandFailed => e
say e.message
rescue Logaling::GlossaryAlreadyRegistered => e
say e.message
end
desc 'import', 'Import external glossary'
method_option "list", type: :boolean, default: false
def import(external_glossary=nil, *args)
require "logaling/external_glossary"
Logaling::ExternalGlossary.load
if options["list"]
Logaling::ExternalGlossary.list.each {|glossary_source| say "#{glossary_source.name.bright} : #{glossary_source.description} (#{glossary_source.url})" }
else
case external_glossary
when 'tmx'
check_import_parameter(args)
url = args[1]
if url && !URI.parse(url).host
url = File.expand_path(url)
end
glossary = Logaling::Glossary.new(args[0], args[2], args[3])
@repository.import_tmx(Logaling::ExternalGlossary.get(external_glossary), glossary, url)
@repository.index
else
@repository.import(Logaling::ExternalGlossary.get(external_glossary))
@repository.index
end
end
rescue Logaling::CommandFailed => e
say e.message
rescue Logaling::ExternalGlossaryNotFound
say "'#{external_glossary}' can't find in import list."
say "Try 'loga import --list' and confirm import list."
rescue Logaling::GlossaryNotFound => e
say e.message
end
desc 'register', 'Register .logaling'
def register
raise Logaling::CommandFailed, "Can't use '-g ' option." if options["glossary"]
@config.check_required_option("glossary" => "Do 'loga register' at project directory.")
raise Logaling::CommandFailed, "Try 'loga new' first." unless File.exist?(@dotfile_path)
register_and_index
say "#{@config.glossary} is now registered to logaling."
rescue Logaling::CommandFailed => e
say e.message
rescue Logaling::GlossaryAlreadyRegistered => e
say "#{@config.glossary} is already registered."
end
desc 'unregister', 'Unregister .logaling'
def unregister
raise Logaling::CommandFailed, "Can't use '-g ' option." if options["glossary"]
@config.check_required_option("glossary" => "Do 'loga unregister' at project directory.")
project = @repository.find_project(@config.glossary)
@repository.unregister(project)
@repository.index
say "#{@config.glossary} is now unregistered."
rescue Logaling::CommandFailed => e
say e.message
rescue Logaling::ProjectNotFound => e
say "#{@config.glossary} is not yet registered."
end
desc 'config [KEY] [VALUE] [--global(optional)]', 'Set config.'
method_option "global", type: :boolean, default: false
def config(key, value)
if options["global"]
unless File.exist?(@logaling_home)
FileUtils.mkdir_p(@logaling_home) rescue raise Logaling::CommandFailed, "Input existing directory as logaling-home."
end
config_path = File.join(@logaling_home, "config")
else
raise Logaling::CommandFailed, "Can't found .logaling" unless @project_config_path
config_path = @project_config_path
end
config = Logaling::Config.load(config_path)
config.add(key, value)
config.save(config_path)
say "Successfully set config."
rescue Logaling::CommandFailed => e
say e.message
end
desc 'add [SOURCE TERM] [TARGET TERM] [NOTE(optional)]', 'Add term to glossary.'
def add(source_term, target_term, note='')
required_options = {
"glossary" => "input glossary name '-g '",
"source-language" => "input source-language code '-S '",
"target-language" => "input target-language code '-T '"
}
@config.check_required_option(required_options)
check_logaling_home_exists
project = @repository.find_project(@config.glossary)
raise Logaling::ProjectNotFound unless project
raise Logaling::ProjectNotFound if project.imported?
glossary = project.glossary(@config.source_language, @config.target_language)
glossary.add(source_term, target_term, note)
rescue Logaling::CommandFailed => e
say e.message
rescue Logaling::TermError => e
say "term '#{source_term}: #{target_term}' already exists in '#{@config.glossary}'"
rescue Logaling::GlossaryNotFound => e
say "Try 'loga new or register' first."
rescue Logaling::ProjectNotFound
say "glossary <#{@config.glossary}> not found."
say "Try 'loga list' and confirm glossary name."
end
desc 'delete [SOURCE TERM] [TARGET TERM(optional)] [--force(optional)]', 'Delete term.'
method_option "force", type: :boolean, default: false
def delete(source_term, target_term=nil)
required_options = {
"glossary" => "input glossary name '-g '",
"source-language" => "input source-language code '-S '",
"target-language" => "input target-language code '-T '"
}
@config.check_required_option(required_options)
check_logaling_home_exists
project = @repository.find_project(@config.glossary)
raise Logaling::ProjectNotFound unless project
glossary = project.glossary(@config.source_language, @config.target_language)
if target_term
glossary.delete(source_term, target_term)
else
glossary.delete_all(source_term, options["force"])
end
rescue Logaling::CommandFailed, Logaling::TermError => e
say e.message
rescue Logaling::GlossaryNotFound => e
say "Try 'loga new or register' first."
rescue Logaling::ProjectNotFound
say "glossary <#{@config.glossary}> not found."
say "Try 'loga list' and confirm glossary name."
end
desc 'update [SOURCE TERM] [TARGET TERM] [NEW TARGET TERM] [NOTE(optional)]', 'Update term.'
def update(source_term, target_term, new_target_term, note='')
required_options = {
"glossary" => "input glossary name '-g '",
"source-language" => "input source-language code '-S '",
"target-language" => "input target-language code '-T '"
}
@config.check_required_option(required_options)
check_logaling_home_exists
project = @repository.find_project(@config.glossary)
raise Logaling::ProjectNotFound unless project
glossary = project.glossary(@config.source_language, @config.target_language)
glossary.update(source_term, target_term, new_target_term, note)
rescue Logaling::CommandFailed => e
say e.message
rescue Logaling::TermError => e
say "term '#{source_term}: #{new_target_term}' already exists in '#{@config.glossary}'"
rescue Logaling::GlossaryNotFound => e
say "Try 'loga new or register' first."
rescue Logaling::ProjectNotFound
say "glossary <#{@config.glossary}> not found."
say "Try 'loga list' and confirm glossary name."
end
desc 'lookup [TERM]', 'Lookup terms.'
method_option "output", type: :string, default: "terminal"
method_option "no-pager", type: :boolean, default: false
method_option "no-color", type: :boolean, default: false
method_option "dictionary", type: :boolean, default: false, aliases: "--dict"
method_option "fixed", type: :boolean, default: false
def lookup(source_term)
check_logaling_home_exists
@repository.index
if @config.glossary
project = @repository.find_project(@config.glossary)
raise Logaling::ProjectNotFound unless project
glossary = project.glossary(@config.source_language, @config.target_language)
else
glossary = nil
end
terms = @repository.lookup(source_term, glossary, options)
unless terms.empty?
run_pager
terms.each_with_index do |term, i|
case options["output"]
when "terminal"
term_renderer = Logaling::Command::Renderers::TermDefaultRenderer.new(term, @repository, @config, options)
term_renderer.set_max_source_term_width(terms)
term_renderer.render($stdout)
when "csv"
term_renderer = Logaling::Command::Renderers::TermCsvRenderer.new(term, @repository, @config, options)
term_renderer.render($stdout)
when "json"
term_renderer = Logaling::Command::Renderers::TermJsonRenderer.new(term, @repository, @config, options)
term_renderer.index = i
term_renderer.last_index = terms.length
term_renderer.render($stdout)
end
end
else
"source-term <#{source_term}> not found"
end
rescue Logaling::ProjectNotFound
say "glossary <#{@config.glossary}> not found."
say "Try 'loga list' and confirm glossary name."
rescue Logaling::CommandFailed, Logaling::TermError => e
say e.message
end
desc 'version', 'Show version.'
def version
say "logaling-command version #{Logaling::Command::VERSION}"
end
desc 'show', 'Show terms in glossary.'
method_option "no-pager", type: :boolean, default: false
method_option "annotation", type: :string, aliases: "-A"
def show
required_options = {
"glossary" => "input glossary name '-g '",
"source-language" => "input source-language code '-S '",
"target-language" => "input target-language code '-T '"
}
@config.check_required_option(required_options)
check_logaling_home_exists
glossary = @repository.find_glossary(@config.glossary, @config.source_language, @config.target_language)
raise Logaling::GlossaryNotFound unless glossary
terms = glossary.terms(options["annotation"])
unless terms.empty?
run_pager
terms.each do |term|
term_renderer = Logaling::Command::Renderers::TermDefaultRenderer.new(term, @repository, @config, options)
term_renderer.set_max_source_term_width(terms)
term_renderer.hide_glossary_name
term_renderer.render($stdout)
end
else
"glossary <#{@config.glossary}> not found"
end
rescue Logaling::CommandFailed, Logaling::GlossaryDBNotFound => e
say e.message
rescue Logaling::GlossaryNotFound
say "glossary <#{@config.glossary}> not found."
say "Try 'loga list' and confirm glossary name."
end
desc 'list', 'Show glossary list.'
method_option "no-pager", type: :boolean, default: false
def list
check_logaling_home_exists
@repository.index
projects = @repository.projects
unless projects.empty?
run_pager
# 用語集の一覧といいつつプロジェクトの一覧を出していて、
# かつ個人用のプロジェクトと .logaling によるプロジェクトで
# プロジェクトとして表現しているスコープが異なっているために、
# 重複した名前のプロジェクトが表示されるケースが存在する
#TODO 表示する情報の単位を整理後に見直す
projects.map(&:name).uniq.each do |project_name|
printf(" %s\n", project_name)
end
else
"There is no registered glossary."
end
rescue Logaling::CommandFailed, Logaling::GlossaryDBNotFound => e
say e.message
end
desc 'copy [GLOSSARY NAME] [SOURCE LANGUAGE] [TARGET LANGUAGE] [NEW GLOSSARY NAME] [NEW SOURCE LANGUAGE] [NEW TARGET LANGUAGE]', 'Copy personal glossary'
def copy(project_name, source_language, target_language, new_project_name, new_source_language, new_target_language)
check_logaling_home_exists
src_glossary = @repository.find_glossary(project_name, source_language, target_language)
unless src_glossary
raise Logaling::GlossaryNotFound, "Can't found #{project_name}.#{source_language}.#{target_language}"
end
dest_project = @repository.create_personal_project(new_project_name, new_source_language, new_target_language)
dest_glossary = dest_project.glossary(new_source_language, new_target_language)
dest_glossary.merge!(src_glossary)
rescue Logaling::CommandFailed, Logaling::GlossaryAlreadyRegistered, Logaling::GlossaryNotFound => e
say e.message
end
private
def error(msg)
STDERR.puts(msg)
exit 1
end
def logaling_config_path
if options["logaling-config"]
options["logaling-config"]
else
File.join(Dir.pwd, LOGALING_CONFIG)
end
end
def run_pager
Pager.run unless options["no-pager"]
end
def check_logaling_home_exists
unless File.exist?(@logaling_home)
raise Logaling::CommandFailed, "Input existing directory as logaling-home."
end
end
def check_import_parameter(args)
unless args[0] && args[1]
raise Logaling::CommandFailed, "Do 'loga import tmx '"
end
end
def register_and_index
@repository.register(@dotfile_path, @config.glossary)
@repository.index
end
end
end