# File lib/rouge/cli.rb, line 155
      def self.doc
        return enum_for(:doc) unless block_given?

        yield %[usage: rougify highlight <filename> [options...]]
        yield %[       rougify highlight [options...]]
        yield %[]
        yield %[--input-file|-i <filename>  specify a file to read, or - to use stdin]
        yield %[]
        yield %[--lexer|-l <lexer>          specify the lexer to use.]
        yield %[                            If not provided, rougify will try to guess]
        yield %[                            based on --mimetype, the filename, and the]
        yield %[                            file contents.]
        yield %[]
        yield %[--formatter|-f <opts>       specify the output formatter to use.]
        yield %[                            If not provided, rougify will default to]
        yield %[                            terminal256.]
        yield %[]
        yield %[--mimetype|-m <mimetype>    specify a mimetype for lexer guessing]
        yield %[]
        yield %[--lexer-opts|-L <opts>      specify lexer options in CGI format]
        yield %[                            (opt1=val1&opt2=val2)]
        yield %[]
        yield %[--formatter-opts|-F <opts>  specify formatter options in CGI format]
        yield %[                            (opt1=val1&opt2=val2)]
      end

      def self.parse(argv)
        opts = {
          :formatter => 'terminal256',
          :input_file => '-',
          :lexer_opts => {},
          :formatter_opts => {},
        }

        until argv.empty?
          arg = argv.shift
          case arg
          when '--input-file', '-i'
            opts[:input_file] = argv.shift
          when '--mimetype', '-m'
            opts[:mimetype] = argv.shift
          when '--lexer', '-l'
            opts[:lexer] = argv.shift
          when '--formatter', '-f'
            opts[:formatter] = argv.shift
          when '--lexer-opts', '-L'
            opts[:lexer_opts] = parse_cgi(argv.shift)
          when '--formatter-opts', '-F'
            opts[:formatter_opts] = parse_cgi(argv.shift)
          when /^--/
            error! "unknown option #{arg.inspect}"
          else
            opts[:input_file] = arg
          end
        end

        new(opts)
      end

      def input_stream
        @input_stream ||= FileReader.new(@input_file)
      end

      def input
        @input ||= input_stream.read
      end

      def lexer_class
        @lexer_class ||= Lexer.guess(
          :filename => @input_file,
          :mimetype => @mimetype,
          :source => input_stream,
        )
      end

      def lexer
        @lexer ||= lexer_class.new(@lexer_opts)
      end

      attr_reader :input_file, :lexer_name, :mimetype, :formatter

      def initialize(opts={})
        @input_file = opts[:input_file]

        if opts[:lexer]
          @lexer_class = Lexer.find(opts[:lexer]) \
            or error! "unkown lexer #{opts[:lexer].inspect}"
        else
          @lexer_name = opts[:lexer]
          @mimetype = opts[:mimetype]
        end

        @lexer_opts = opts[:lexer_opts]

        formatter_class = Formatter.find(opts[:formatter]) \
          or error! "unknown formatter #{opts[:formatter]}"

        @formatter = formatter_class.new(opts[:formatter_opts])
      end

      def run
        formatter.format(lexer.lex(input), &method(:print))
      end

    private
      def self.parse_cgi(str)
        pairs = CGI.parse(str).map { |k, v| [k.to_sym, v.first] }
        Hash[pairs]
      end
    end