require "magellan/cli" require 'thor' module Magellan module Cli class Base < Thor class_option :version, type: :boolean, aliases: "-v", desc: I18n.t(:version, scope: [:base, :class_option]) class_option :verbose, type: :boolean, aliases: "-V", desc: I18n.t(:verbose, scope: [:base, :class_option]) class_option :dryrun , type: :boolean, aliases: "-D", desc: I18n.t(:dryrun , scope: [:base, :class_option]) no_commands do def sub(klass) task = klass.new task.options = self.options task end def opts @opts ||= options || {} end def dryrun? opts[:dryrun] end def verbose? opts[:verbose] end def log_verbose(msg) self.class.log_verbose(msg) if verbose? end def log_info(msg) self.class.log_info(msg) end def log_success(msg) self.class.log_success(msg) end def log_error(msg) self.class.log_error(msg) end def fatal(msg) log_verbose(caller.join("\n ")) raise Cli::Error, msg end def show_error_and_exit1(e) log_error "[#{e.class}] #{e.message}" log_verbose(" " << e.backtrace.join("\n ")) exit(1) end end class << self def puts_with_color(color_no, msg) $stderr.puts("\e[#{color_no}m#{msg}\e[0m") end def log_verbose(msg, flag = true) puts_with_color(34, msg) if flag end def log_info(msg) puts_with_color(0, msg) end def log_success(msg) puts_with_color(32, msg) end def log_error(msg) puts_with_color(31, msg) end def sorted_commands(all = true) cmd_hash = all_commands.dup Thor::Util.thor_classes_in(self).each do |klass| cmd_hash.update(klass.commands) end if order = self.const_get(:COMMAND_ORDER) rescue nil result = order.map{|i| cmd_hash[i]} result += (cmd_hash.keys - order).map{|i| cmd_hash[i]} else result = cmd_hash.values end if idx = result.index{|cmd| cmd.name == "help" } h = result.delete_at(idx) result << h end return result end def sorted_printable_commands(all = true, subcommand = false) list = printable_commands(all, subcommand) Thor::Util.thor_classes_in(self).each do |klass| list += klass.printable_commands(false) end order = self.const_get(:COMMAND_ORDER) rescue nil if order orig = list list = order.map do |ptn| idx = orig.index{|t| t.first =~ /\b#{ptn}\b/} raise "#{ptn} not found" unless idx orig.delete_at(idx) end list += orig # add items not in COMMAND_ORDER end # # don't sort in alphabetical order # list.sort! { |a, b| a[0] <=> b[0] } # move help to the end of list if idx = list.index{|t| t.first =~ /\bhelp\b/ } h = list.delete_at(idx) list << h end return list end def update_common_help_message if cmd = all_commands["help"] cmd.description = I18n.t(:help, scope: [:base, :cmd]) end end # overwrite Thor.help method def help(shell, subcommand = false) update_common_help_message if defined?(@package_name) && @package_name shell.say "#{@package_name} commands:" else shell.say "Commands:" end shell.print_table(sorted_printable_commands(true, subcommand), :indent => 2, :truncate => true) shell.say class_options_help(shell) end # override Thor.command_help def command_help(shell, command_name) meth = normalize_command_name(command_name) command = all_commands[meth] handle_no_command_error(meth) unless command shell.say "Usage:" shell.say " #{banner(command)}" shell.say class_options_help(shell, nil => command.options.map { |_, o| o }) if command.long_description shell.say "Description:" shell.print_wrapped(command.long_description, :indent => 2) else shell.say command.description end end end end end end