# -*- coding: utf-8 -*- # # Copyright 2013 whiteleaf. All rights reserved. # require "optparse" module Command class CommandBase # postfixies は改行で区切ることで2パターン以上記述できる def initialize(postfixies = "") @opt = OptionParser.new(nil, 20) command_name = self.class.to_s.scan(/::(.+)$/)[0][0].downcase banner = postfixies.split("\n").map.with_index { |postfix, i| (i == 0 ? "Usage: " : " or: ") + "narou #{command_name} #{postfix}" }.join("\n") @opt.banner = "#{TermColorLight.escape(banner)}".termcolor @options = {} # ヘルプを見やすく色付け def @opt.help msg = super # 見出し部分 msg.gsub!(/((?:Examples|Options|Configuration|[^\s]+? Variable List):)/) do "#{$1}".termcolor end # Examples のコメント部分 msg.gsub!(/(#.+)$/) do "#{TermColorLight.escape($1)}".termcolor end # 文字列部分 msg.gsub!(/(".+?")/) do "#{TermColorLight.escape($1)}".termcolor end msg end end def execute(argv) @options.clear load_local_settings @opt.parse!(argv) rescue OptionParser::InvalidOption => e error "不明なオプションです(#{e})" exit 1 rescue OptionParser::MissingArgument => e error "オプションの引数が指定されていないか正しくありません(#{e})" exit 1 end def load_local_settings command_prefix = self.class.to_s.scan(/[^:]+$/)[0].downcase local_settings = Inventory.load("local_setting", :local) local_settings.each do |name, value| if name =~ /^#{command_prefix}\.(.+)$/ @options[$1] = value end end end # # タグ情報をID情報に展開する # def tagname_to_ids(array) database = Database.instance tag_index = Hash.new { [] } database.each do |id, data| tags = data["tags"] || [] tags.each do |tag| tag_index[tag] |= [id] end end array.map! { |arg| ids = tag_index[arg] ids.empty? ? arg : ids }.flatten! end # # 普通にコマンドを実行するけど、exit(2) を補足してexitstatus を返す # 正常終了なら0 # def self.execute!(argv) self.new.execute(argv) rescue SystemExit => e e.status else 0 end def self.oneline_help "" end # # 指定したメソッドを呼び出す際に、フック関数があればそれ経由で呼ぶ # # 指定したメソッドは存在しなくてもいい。存在しなければ空のProcが作られる # def hook_call(target_method, *argv) hook = "hook_#{target_method}" target_method_proc = self.method(target_method) rescue ->{} if respond_to?(hook) self.__send__(hook, *argv, &target_method_proc) else target_method_proc.call(*argv) end end # # 設定の強制設定 # def force_change_settings_function(pairs) settings = Inventory.load("local_setting", :local) modified = false pairs.each do |name, value| if settings[name].nil? || settings[name] != value settings[name] = value puts "#{name} を #{value} に強制変更しました".termcolor modified = true end end settings.save if modified end end end