class HammerCLI::AbstractCommand

Attributes

validation_blocks[RW]

Public Class Methods

add_sets_help(help) click to toggle source
# File lib/hammer_cli/abstract.rb, line 63
def add_sets_help(help)
  sets_details = HammerCLI::Help::Section.new(_('Predefined field sets'), nil, id: :s_sets_details, richtext: true)
  sets_details.definition << HammerCLI::Help::Text.new(output_definition.sets_table)
  help.definition.unshift(sets_details)
end
build_options(builder_params={}) { |builder_params| ... } click to toggle source
# File lib/hammer_cli/abstract.rb, line 188
def self.build_options(builder_params={})
  builder_params = yield(builder_params) if block_given?

  option_builder.build(builder_params).each do |option|
    # skip switches that are already defined
    next if option.nil? || option.switches.any? { |s| find_option(s) }

    adjust_family(option) if option.respond_to?(:family)
    declared_options << option
    block ||= option.default_conversion_block
    define_accessors_for(option, &block)
    extend_options_help(option) if option.value_formatter.is_a?(HammerCLI::Options::Normalizers::ListNested)
    completion_type_for(option)
  end
end
command_extensions() click to toggle source
# File lib/hammer_cli/abstract.rb, line 30
def command_extensions
  @command_extensions = @command_extensions || inherited_command_extensions || []
  @command_extensions
end
extend_help(&block) click to toggle source
# File lib/hammer_cli/abstract.rb, line 147
def self.extend_help(&block)
  # We save the block for execution on object level, where we can access command's context and check :is_tty? flag
  self.help_extension_blocks << block
end
extend_options_help(option) click to toggle source
# File lib/hammer_cli/abstract.rb, line 44
def extend_options_help(option)
  extend_help do |h|
    begin
      h.find_item(:s_option_details)
    rescue ArgumentError
      option_details = HammerCLI::Help::Section.new(_('Option details'), nil, id: :s_option_details, richtext: true)
      option_details.definition << HammerCLI::Help::Text.new(
        _('Following parameters accept format defined by its schema ' \
          '(bold are required; <> contain acceptable type; [] contain acceptable value):')
      )
      h.definition.unshift(option_details)
    ensure
      h.find_item(:s_option_details).definition << HammerCLI::Help::List.new([
        [option.switches.last, option.value_formatter.schema.description]
      ])
    end
  end
end
extend_output_definition(&block) click to toggle source
# File lib/hammer_cli/abstract.rb, line 152
def self.extend_output_definition(&block)
  block.call(output_definition)
rescue ArgumentError => e
  handler = HammerCLI::ExceptionHandler.new
  handler.handle_exception(e)
end
extend_with(*extensions) click to toggle source
# File lib/hammer_cli/abstract.rb, line 204
def self.extend_with(*extensions)
  extensions.each do |extension|
    unless extension.is_a?(HammerCLI::CommandExtensions)
      raise ArgumentError, _('Command extensions should be inherited from %s.') % HammerCLI::CommandExtensions
    end
    extension.delegatee(self)
    extension.extend_predefined_options(self)
    extension.extend_options(self)
    extension.extend_option_family(self)
    extension.extend_output(self)
    extension.extend_help(self)
    logger('Extensions').info "Applied #{extension.details} on #{self}."
    command_extensions << extension
  end
end
help(invocation_path, builder = HammerCLI::Help::Builder.new) click to toggle source
Calls superclass method
# File lib/hammer_cli/abstract.rb, line 128
def self.help(invocation_path, builder = HammerCLI::Help::Builder.new)
  super(invocation_path, builder)
  help_extension = HammerCLI::Help::TextBuilder.new(builder.richtext)
  fields_switch = HammerCLI::Options::Predefined::OPTIONS[:fields].first[0]
  add_sets_help(help_extension) if find_option(fields_switch)
  unless help_extension_blocks.empty?
    help_extension_blocks.each do |extension_block|
      begin
        extension_block.call(help_extension)
      rescue ArgumentError => e
        handler = HammerCLI::ExceptionHandler.new
        handler.handle_exception(e)
      end
    end
  end
  builder.add_text(help_extension.string)
  builder.string
end
help_extension_blocks() click to toggle source
# File lib/hammer_cli/abstract.rb, line 26
def help_extension_blocks
  @help_extension_blocks ||= []
end
inherited_command_extensions() click to toggle source
# File lib/hammer_cli/abstract.rb, line 35
def inherited_command_extensions
  extensions = nil
  if superclass.respond_to?(:command_extensions)
    parent_extensions = superclass.command_extensions.select(&:inheritable?)
    extensions = parent_extensions.dup unless parent_extensions.empty?
  end
  extensions
end
new(*args) click to toggle source
Calls superclass method
# File lib/hammer_cli/abstract.rb, line 114
def initialize(*args)
  super
  context[:path] ||= []
  context[:path] << self
end
option_builder() click to toggle source
# File lib/hammer_cli/abstract.rb, line 183
def self.option_builder
  @option_builder ||= create_option_builder
  @option_builder
end
output(definition=nil, &block) click to toggle source
# File lib/hammer_cli/abstract.rb, line 159
def self.output(definition=nil, &block)
  dsl = HammerCLI::Output::Dsl.new
  dsl.build &block if block_given?
  output_definition.append definition.fields unless definition.nil?
  output_definition.append dsl.fields
end
output_definition() click to toggle source
# File lib/hammer_cli/abstract.rb, line 174
def self.output_definition
  @output_definition = @output_definition || inherited_output_definition || HammerCLI::Output::Definition.new
  @output_definition
end
use_option(*names) click to toggle source
# File lib/hammer_cli/abstract.rb, line 220
def self.use_option(*names)
  names.each do |name|
    HammerCLI::Options::Predefined.use(name, self)
  end
end
validate_options(mode=:append, target_name=nil, validator: nil, &block) click to toggle source
# File lib/hammer_cli/abstract.rb, line 100
def self.validate_options(mode=:append, target_name=nil, validator: nil, &block)
  validator ||= HammerCLI::Options::Validators::DSLBlockValidator.new(&block)
  self.validation_blocks ||= []
  self.validation_blocks << [mode, target_name, validator]
end

Protected Class Methods

autoload_subcommands() click to toggle source
# File lib/hammer_cli/abstract.rb, line 315
def self.autoload_subcommands
  commands = constants.map { |c| const_get(c) }.select { |c| c <= HammerCLI::AbstractCommand }
  commands.each do |cls|
    subcommand(cls.command_name, cls.desc, cls, warning: cls.warning)
  end
end
command_name(name=nil) click to toggle source
# File lib/hammer_cli/abstract.rb, line 296
def self.command_name(name=nil)
  if @names && name
    @names << name if !@names.include?(name)
  else
    @names = [name] if name
  end
  @names || (superclass.respond_to?(:command_names) ? superclass.command_names : nil)
end
command_names(*names) click to toggle source
# File lib/hammer_cli/abstract.rb, line 305
def self.command_names(*names)
  @names = names unless names.empty?
  @names || (superclass.respond_to?(:command_names) ? superclass.command_names : nil)
end
completion_map() click to toggle source
# File lib/hammer_cli/abstract.rb, line 376
def self.completion_map
  completion = {}
  # collect options
  recognised_options.each do |opt|
    opt.switches.each do |switch|
      completion[switch] = completion_types.fetch(switch, {})
    end
  end
  # collect subcommands recursively
  recognised_subcommands.each do |cmd|
    completion[cmd.names.first] = cmd.subcommand_class.completion_map
  end
  # collect params
  completion[:params] = completion_types[:params] unless completion_types[:params].empty?
  completion
end
completion_type_for(option, opts = {}) click to toggle source
# File lib/hammer_cli/abstract.rb, line 397
def self.completion_type_for(option, opts = {})
  completion_type = opts.delete(:completion)
  completion_type ||= option.completion_type(opts[:format])
  [option.switches].flatten(1).each { |s| completion_types[s] = completion_type }
end
completion_types() click to toggle source
# File lib/hammer_cli/abstract.rb, line 393
def self.completion_types
  @completion_types ||= { :params => [] }
end
create_option_builder() click to toggle source
# File lib/hammer_cli/abstract.rb, line 248
def self.create_option_builder
  OptionBuilderContainer.new
end
define_simple_writer_for(attribute, &block) click to toggle source
# File lib/hammer_cli/abstract.rb, line 322
def self.define_simple_writer_for(attribute, &block)
  define_method(attribute.write_method) do |value|
    value = instance_exec(value, &block) if block
    if attribute.respond_to?(:context_target) && attribute.context_target
      context[attribute.context_target] = value
    end
    attribute.of(self).set(value)
  end
end
desc(desc=nil) click to toggle source
# File lib/hammer_cli/abstract.rb, line 291
def self.desc(desc=nil)
  @desc = desc if desc
  @desc
end
find_options(switch_filter, other_filters={}) click to toggle source
# File lib/hammer_cli/abstract.rb, line 234
def self.find_options(switch_filter, other_filters={})
  filters = other_filters
  if switch_filter.is_a? Hash
    filters.merge!(switch_filter)
  else
    filters[:long_switch] = switch_filter
  end

  m = HammerCLI::Options::Matcher.new(filters)
  recognised_options.find_all do |opt|
    m.matches? opt
  end
end
logger(name=self) click to toggle source
# File lib/hammer_cli/abstract.rb, line 264
def self.logger(name=self)
  logger = Logging.logger[name]
  logger.extend(HammerCLI::Logger::Watch) if not logger.respond_to? :watch
  logger
end
option(switches, type, description, opts = {}, &block) click to toggle source
# File lib/hammer_cli/abstract.rb, line 332
def self.option(switches, type, description, opts = {}, &block)
  option = HammerCLI::Options::OptionDefinition.new(switches, type, description, opts).tap do |option|
    declared_options << option
    block ||= option.default_conversion_block
    define_accessors_for(option, &block)
    completion_type_for(option, opts)
  end
  extend_options_help(option) if option.value_formatter.is_a?(HammerCLI::Options::Normalizers::ListNested)
  option
end
option_family(options = {}, &block) click to toggle source
# File lib/hammer_cli/abstract.rb, line 228
def self.option_family(options = {}, &block)
  options[:creator] ||= self
  family = HammerCLI::Options::OptionFamily.new(options)
  family.instance_eval(&block)
end
warning(message = nil) click to toggle source
# File lib/hammer_cli/abstract.rb, line 310
def self.warning(message = nil)
  @warning_msg = message if message
  @warning_msg
end

Private Class Methods

adjust_family(option) click to toggle source
# File lib/hammer_cli/abstract.rb, line 405
def self.adjust_family(option)
  # Collect options that should share the same family
  # If those options have family, adopt the current one
  # Else adopt those options to the family of the current option
  # NOTE: this shouldn't rewrite any options,
  # although options from similar family could be adopted (appended)
  options = find_options(
    aliased_resource: option.aliased_resource.to_s
  ).select { |o| o.family.nil? || o.family.formats.include?(option.value_formatter.class) }.group_by do |o|
    next :to_skip if option.family.children.include?(o)
    next :to_adopt if o.family.nil? || o.family.head.nil?
    next :to_skip if o.family.children.include?(option)
    # If both family heads handle the same switch
    # then `option` is probably from similar family and can be adopted
    next :adopt_by if option.family.head.nil? || o.family.head.handles?(option.family.head.long_switch)

    :to_skip
  end
  options[:to_adopt]&.each do |child|
    option.family&.adopt(child)
  end
  options[:adopt_by]&.map(&:family)&.uniq&.each do |family|
    family.adopt(option)
  end
end
inherited_output_definition() click to toggle source
# File lib/hammer_cli/abstract.rb, line 431
def self.inherited_output_definition
  od = nil
  if superclass.respond_to? :output_definition
    od_super = superclass.output_definition
    od = od_super.dup unless od_super.nil?
  end
  od
end

Public Instance Methods

adapter() click to toggle source
# File lib/hammer_cli/abstract.rb, line 70
def adapter
  :base
end
exception_handler() click to toggle source
# File lib/hammer_cli/abstract.rb, line 110
def exception_handler
  @exception_handler ||= exception_handler_class.new(:output => output)
end
execute() click to toggle source
# File lib/hammer_cli/abstract.rb, line 96
def execute
  HammerCLI::EX_OK
end
help() click to toggle source
# File lib/hammer_cli/abstract.rb, line 124
def help
  self.class.help(invocation_path, HammerCLI::Help::Builder.new(context[:is_tty?]))
end
interactive?() click to toggle source
# File lib/hammer_cli/abstract.rb, line 179
def interactive?
  HammerCLI.interactive?
end
output() click to toggle source
# File lib/hammer_cli/abstract.rb, line 166
def output
  @output ||= HammerCLI::Output::Output.new(context, :default_adapter => adapter)
end
output_definition() click to toggle source
# File lib/hammer_cli/abstract.rb, line 170
def output_definition
  self.class.output_definition
end
parent_command() click to toggle source
# File lib/hammer_cli/abstract.rb, line 120
def parent_command
  context[:path][-2]
end
parse(arguments) click to toggle source
Calls superclass method
# File lib/hammer_cli/abstract.rb, line 88
def parse(arguments)
  super
  validate_options
  logger.info "Called with options: %s" % options.inspect
rescue HammerCLI::Options::Validators::ValidationError => e
  signal_usage_error e.message
end
run(arguments) click to toggle source
Calls superclass method
# File lib/hammer_cli/abstract.rb, line 74
def run(arguments)
  begin
    begin
      exit_code = super
      context.delete(:fields)
      raise "exit code must be integer" unless exit_code.is_a? Integer
    rescue => e
      exit_code = handle_exception(e)
    end
    logger.debug 'Retrying the command' if (exit_code == HammerCLI::EX_RETRY)
  end while (exit_code == HammerCLI::EX_RETRY)
  return exit_code
end
validate_options() click to toggle source
# File lib/hammer_cli/abstract.rb, line 106
def validate_options
  # keep the method for legacy reasons
end

Protected Instance Methods

add_validators(sources) click to toggle source
# File lib/hammer_cli/abstract.rb, line 367
def add_validators(sources)
  if self.class.validation_blocks
    self.class.validation_blocks.each do |validation_block|
      sources.insert_relative(*validation_block)
    end
  end
  sources
end
all_options() click to toggle source
# File lib/hammer_cli/abstract.rb, line 343
def all_options
  option_collector.all_options
end
exception_handler_class() click to toggle source
# File lib/hammer_cli/abstract.rb, line 283
def exception_handler_class
  #search for exception handler class in parent modules/classes
  HammerCLI.constant_path(self.class.name.to_s).reverse.each do |mod|
    return mod.send(:exception_handler_class) if mod.respond_to? :exception_handler_class
  end
  return HammerCLI::ExceptionHandler
end
handle_exception(e) click to toggle source
# File lib/hammer_cli/abstract.rb, line 279
def handle_exception(e)
  exception_handler.handle_exception(e)
end
logger(name=self.class) click to toggle source
# File lib/hammer_cli/abstract.rb, line 270
def logger(name=self.class)
  self.class.logger(name)
end
option_collector() click to toggle source
# File lib/hammer_cli/abstract.rb, line 351
def option_collector
  @option_collector ||= HammerCLI::Options::OptionCollector.new(self.class.recognised_options, add_validators(option_sources))
end
option_sources() click to toggle source
# File lib/hammer_cli/abstract.rb, line 355
def option_sources
  sources = HammerCLI::Options::ProcessorList.new(name: 'DefaultInputs')
  sources << HammerCLI::Options::Sources::CommandLine.new(self)
  sources << HammerCLI::Options::Sources::SavedDefaults.new(context[:defaults], logger) if context[:use_defaults]

  sources = HammerCLI::Options::ProcessorList.new([sources])
  self.class.command_extensions.each do |extension|
    extension.extend_option_sources(sources, self)
  end
  sources
end
options() click to toggle source
# File lib/hammer_cli/abstract.rb, line 347
def options
  option_collector.options
end
print_collection(definition, collection, options = {}) click to toggle source
print_message(msg, msg_params = {}, options = {}) click to toggle source
print_record(definition, record) click to toggle source
validator() click to toggle source
# File lib/hammer_cli/abstract.rb, line 274
def validator
  # keep the method for legacy reasons, it's used by validate_options
  @validator ||= HammerCLI::Options::Validators::DSL.new(self.class.recognised_options, all_options)
end