# frozen_string_literal: true class Pry class Slop class Commands include Enumerable attr_reader :config, :commands, :arguments attr_writer :banner # Create a new instance of Slop::Commands and optionally build # Slop instances via a block. Any configuration options used in # this method will be the default configuration options sent to # each Slop object created. # # config - An optional configuration Hash. # block - Optional block used to define commands. # # Examples: # # commands = Slop::Commands.new do # on :new do # on '-o', '--outdir=', 'The output directory' # on '-v', '--verbose', 'Enable verbose mode' # end # # on :generate do # on '--assets', 'Generate assets', :default => true # end # # global do # on '-D', '--debug', 'Enable debug mode', :default => false # end # end # # commands[:new].class #=> Slop # commands.parse # def initialize(config = {}, &block) @config = config @commands = {} @banner = nil @triggered_command = nil warn "[DEPRECATED] Slop::Commands is deprecated and will be removed in "\ "Slop version 4. Check out http://injekt.github.com/slop/#commands for "\ "a new implementation of commands." return unless block_given? block.arity == 1 ? yield(self) : instance_eval(&block) end # Optionally set the banner for this command help output. # # banner - The String text to set the banner. # # Returns the String banner if one is set. def banner(banner = nil) @banner = banner if banner @banner end # Add a Slop instance for a specific command. # # command - A String or Symbol key used to identify this command. # config - A Hash of configuration options to pass to Slop. # block - An optional block used to pass options to Slop. # # Returns the newly created Slop instance mapped to command. def on(command, config = {}, &block) commands[command.to_s] = Slop.new(@config.merge(config), &block) end # Add a Slop instance used when no other commands exist. # # config - A Hash of configuration options to pass to Slop. # block - An optional block used to pass options to Slop. # # Returns the newly created Slop instance mapped to default. def default(config = {}, &block) on('default', config, &block) end # Add a global Slop instance. # # config - A Hash of configuration options to pass to Slop. # block - An optional block used to pass options to Slop. # # Returns the newly created Slop instance mapped to global. def global(config = {}, &block) on('global', config, &block) end # Fetch the instance of Slop tied to a command. # # key - The String or Symbol key used to locate this command. # # Returns the Slop instance if this key is found, nil otherwise. def [](key) commands[key.to_s] end alias get [] # Check for a command presence. # # Examples: # # cmds.parse %w( foo ) # cmds.present?(:foo) #=> true # cmds.present?(:bar) #=> false # # Returns true if the given key is present in the parsed arguments. def present?(key) key.to_s == @triggered_command end # Enumerable interface. def each(&block) @commands.each(&block) end # Parse a list of items. # # items - The Array of items to parse. # # Returns the original Array of items. def parse(items = ARGV) parse! items.dup items end # Parse a list of items, removing any options or option arguments found. # # items - The Array of items to parse. # # Returns the original Array of items with options removed. def parse!(items = ARGV) if (opts = commands[items[0].to_s]) @triggered_command = items.shift execute_arguments! items opts.parse! items elsif (opts = commands['default']) opts.parse! items elsif config[:strict] && items[0] raise InvalidCommandError, "Unknown command `#{items[0]}`" end execute_global_opts! items items end # Returns a nested Hash with Slop options and values. See Slop#to_hash. def to_hash Hash[commands.map { |k, v| [k.to_sym, v.to_hash] }] end # Returns the help String. def to_s defaults = commands.delete('default') globals = commands.delete('global') helps = commands.reject { |_, v| v.options.none? } helps['Global options'] = globals.to_s if globals && globals.options.any? helps['Other options'] = defaults.to_s if defaults && defaults.options.any? banner = @banner ? "#{@banner}\n" : "" banner + helps.map { |key, opts| " #{key}\n#{opts}" }.join("\n\n") end alias help to_s # Returns the inspection String. def inspect "#" end private # Returns nothing. def execute_arguments!(items) @arguments = items.take_while { |arg| !arg.start_with?('-') } items.shift @arguments.size end # Returns nothing. def execute_global_opts!(items) return unless (global_opts = commands['global']) global_opts.parse!(items) end end end end