def run(opts_and_args, parent_opts = {}, hard_exit: true)
      # Parse up to command name
      stuff = partition(opts_and_args)
      opts_before_subcmd, subcmd_name, opts_and_args_after_subcmd = *stuff

      if subcommands.empty? || (subcmd_name.nil? && !block.nil?)
        run_this(opts_and_args, parent_opts)
      else
        # Handle options
        handle_options(opts_before_subcmd)

        # Get command
        if subcmd_name.nil?
          if default_subcommand_name
            subcmd_name = default_subcommand_name
          else
            warn "#{name}: no command given"
            raise CriExitException.new(is_error: true)
          end
        end
        subcommand = command_named(subcmd_name, hard_exit: hard_exit)
        return if subcommand.nil?

        # Run
        subcommand.run(opts_and_args_after_subcmd, parent_opts.merge(opts_before_subcmd), hard_exit: hard_exit)
      end
    rescue CriExitException => e
      exit(e.error? ? 1 : 0) if hard_exit
    end
def run(opts_and_args, parent_opts = {}, hard_exit: true)
      # Parse up to command name
      stuff = partition(opts_and_args)
      opts_before_subcmd, subcmd_name, opts_and_args_after_subcmd = *stuff

      if subcommands.empty? || (subcmd_name.nil? && !block.nil?)
        run_this(opts_and_args, parent_opts)
      else
        # Handle options
        handle_options(opts_before_subcmd)

        # Get command
        if subcmd_name.nil?
          if default_subcommand_name
            subcmd_name = default_subcommand_name
          else
            warn "#{name}: no command given"
            raise CriExitException.new(is_error: true)
          end
        end
        subcommand = command_named(subcmd_name, hard_exit: hard_exit)
        return if subcommand.nil?

        # Run
        subcommand.run(opts_and_args_after_subcmd, parent_opts.merge(opts_before_subcmd), hard_exit: hard_exit)
      end
    rescue CriExitException => e
      exit(e.error? ? 1 : 0) if hard_exit
    end
Runs the command with the given command-line arguments, possibly invoking
 subcommands and passing on the options and arguments.

 @param [Array<String>] opts_and_args A list of unparsed arguments

 @param [Hash] parent_opts A hash of options already handled by the
   supercommand

 @return [void]