# File lib/slop.rb, line 223
  def parse!(items = ARGV, &block)
    if items.empty? && @callbacks[:empty]
      @callbacks[:empty].each { |cb| cb.call(self) }
      return items
    end

    # reset the trash so it doesn't carry over if you parse multiple
    # times with the same instance
    @trash.clear

    if cmd = @commands[items[0]]
      items.shift
      return cmd.parse! items
    end

    items.each_with_index do |item, index|
      @trash << index && break if item == '--'
      autocreate(items, index) if config[:autocreate]
      process_item(items, index, &block) unless @trash.include?(index)
    end
    items.reject!.with_index { |item, index| @trash.include?(index) }

    missing_options = options.select { |opt| opt.required? && opt.count < 1 }
    if missing_options.any?
      raise MissingOptionError,
      "Missing required option(s): #{missing_options.map(&:key).join(', ')}"
    end

    if @unknown_options.any?
      raise InvalidOptionError, "Unknown options #{@unknown_options.join(', ')}"
    end

    if @triggered_options.empty? && @callbacks[:no_options]
      @callbacks[:no_options].each { |cb| cb.call(self) }
    end

    if @runner.respond_to?(:call)
      @runner.call(self, items) unless config[:help] and present?(:help)
    end

    items
  end