lib/eco/cli/config/options_set.rb in eco-helpers-2.0.16 vs lib/eco/cli/config/options_set.rb in eco-helpers-2.0.17

- old
+ new

@@ -3,47 +3,140 @@ class Config class OptionsSet include Eco::CLI::Config::Help attr_reader :core_config + class OptConfig < Struct.new(:name, :namespace, :description, :callback) + end + def initialize(core_config:) @core_config = core_config - @options_set = {} - @description = {} + @sets = {} end # @return [String] summary of the options. def help + indent = 2 + spaces = any_non_general_space_active? ? active_namespaces : namespaces + ["The following are the available options:"].yield_self do |lines| - max_len = keys_max_len(@options_set.keys) - @options_set.keys.each do |key| - lines << help_line(key, @description[key], max_len) + max_len = keys_max_len(options_args(spaces)) + indent + spaces.each do |namespace| + is_general = (namespace == :general) + str_indent = is_general ? "" : " " * indent + lines << help_line(namespace, "", max_len) unless is_general + options_set(namespace).each do |arg, option| + lines << help_line(" " * indent + "#{option.name}", option.description, max_len) + end end lines end.join("\n") end - # @param option [String] the command line option. + # @return [Array<String>] all the argument of the options in `namespaces` + def options_args(namespaces) + namespaces.each_with_object([]) do |space, args| + args.concat(options_set(space).keys) + end.uniq + end + + # @param option [String, Array<String>] the command line option(s). + # @param namespace [String] preceding command(s) argument that enables this option. # @param desc [String] description of the option. - def add(option, desc = nil) + def add(option, desc = nil, namespace: :general) raise "Missing block to define the options builder" unless block_given? - callback = Proc.new - [option].flatten.compact.each do |opt| - @options_set[opt] = callback - @description[opt] = desc + + opts = [option].flatten.compact + unless opts.empty? + callback = Proc.new + opts.each do |opt| + puts "Overriding option '#{option}' in '#{namespace}' namespace" if option_exists?(opt, namespace) + options_set(namespace)[opt] = OptConfig.new(opt, namespace, desc, callback) + end end self end def process(io:) unless io && io.is_a?(Eco::API::UseCases::BaseIO) raise "You need to provide Eco::API::UseCases::BaseIO object. Given: #{io.class}" end - @options_set.each do |arg, callback| - callback.call(io.options, io.session) if SCR.get_arg(arg) + active_options.each do |option| + option.callback.call(io.options, io.session) end + io.options + end + + def active_options + @active_options ||= sets.select do |namespace, opts_set| + active_namespace?(namespace) + end.each_with_object([]) do |(namespace, opts_set), options| + opts_set.each do |arg, option| + options << option if active_option?(arg, namespace) + end + end + end + + def all_options + sets.each_with_object([]) do |(namespace, opts_set), options| + options << opts_set.values + end + end + + def namespaces + sets.keys.sort_by do |key| + key == :general + end + end + + def any_non_general_space_active? + (active_namespaces - [:general]).length > 0 + end + + def active_namespaces + @active_namespaces ||= [].tap do |active| + active << :general + other = (namespaces - [:general]).select {|nm| SCR.arg?(nm)} + active.concat(other) + end + end + + + private + + def active_namespace?(namespace) + (namespace == :general) || SCR.get_arg(namespace) + end + + # Is the option active? + # 1. If :general namespace, it does just a direct check + # 2. Otherwise, the `namespace` wording should come first in the `cli` or it is considered inactive + def active_option?(opt, namespace = :general) + if namespace == :general + SCR.get_arg(opt) + else + active_namespace?(namespace) && SCR.arg_order?(namespace, opt) && SCR.get_arg(opt) + end + end + + def option_exists?(opt, namespace = :general) + options_set(namespace).key?(opt) + end + + def sets + @sets ||= { + general: {} + } + end + + def namespaces + @sets.keys + end + + def options_set(namespace = :general) + @sets[namespace] ||= {} end end end end