module Eco class CLI class Config class UseCases include Eco::CLI::Config::Help attr_reader :core_config def initialize(core_config:) @core_config = core_config @linked_cases = {} @description = {} end # @return [String] summary of the use cases. def help ["The following are the available use cases:"].yield_self do |lines| max_len = keys_max_len(@linked_cases.keys) @linked_cases.keys.sort.each do |key| lines << help_line(key, @description[key], max_len) end lines end.join("\n") end # Integrates a usecase to the command line. # @param option_case [String] the command line option to invoke the usecase. # @param type [Symbol] the type of usecase. # @param desc [String] description of the case. # @param case_name [String, nil] the name of the usecase as defined. def add(option_case, type, desc = nil, case_name: nil) Eco::API::UseCases::UseCase.validate_type(type) unless callback = block_given?? Proc.new : nil raise "You must specify a valid 'case_name' when no block is provided" unless case_name raise "'case_name' expected to be a String. Given: #{case_name.class}" unless case_name.is_a?(String) end @linked_cases[option_case] = { type => { option: option_case, type: type, casename: case_name, callback: callback } } @description[option_case] = desc self end # Scopes/identifies which usecases are being invoked from the command line # @note # - this method will sort the active usecases by the position they hold in the command line # @param io [Eco::API::UseCases::BaseIO] the input/output object # @return [Hash] where keys are cases and values a `Hash` with `option` String and `callback` def active(io:) validate_io!(io) return @active_cases unless !@active_cases active_cases = {} @linked_cases.each do |option_case, types| next nil unless SCR.get_arg(option_case) types.each do |type, data| if usecase = get_usecase(io: io, data: data) active_cases[usecase] = { index: SCR.get_arg_index(option_case), option: option_case, callback: data[:callback] } end end end @active_cases = active_cases.sort_by {|c, d| d[:index]}.to_h end def process(io:) validate_io!(io) processed = false active(io: io).each do |usecase, data| raise "Something went wrong when scoping active cases" unless data processed = true io = case_io(io: io, usecase: usecase) # some usecases have a callback to collect the parameters data[:callback]&.call(*io.params) io = usecase.launch(io: io) end processed end private # Gets a `UseCaseIO` def case_io(io:, usecase:) validate_io!(io) case io when Eco::API::UseCases::UseCaseIO io.chain(usecase: usecase) when Eco::API::UseCases::BaseIO params = io.params(keyed: true).merge(usecase: usecase) Eco::API::UseCases::UseCaseIO.new(**params) end end def get_usecase(io:, data:) usecase = if case_name = data[:casename] io.session.usecases.case(case_name, type: data[:type]) end usecase ||= if callback = data[:callback] # identify/retrieve usecase via callback params = io.params(keyed: true).merge(type: data[:type]) io = io.new(**params, validate: false) callback.call(*io.params).tap do |usecase| unless usecase.is_a?(Eco::API::UseCases::UseCase) msg = "When adding a usecase, without specifying 'case_name:', " msg += "the block that integrates usecase for cli option '#{data[:option]}'" msg += " must return an Eco::API::UseCases::UseCase object. It returns #{usecase.class}" raise msg end end end end def validate_io!(io) unless io && io.is_a?(Eco::API::UseCases::BaseIO) raise "You need to provide Eco::API::UseCases::BaseIO object. Given: #{io.class}" end end end end end end