    /*
     *  call-seq:
     *     searcher.highlight(query, doc_id, field, options = {}) -> Array
     *
     *  Returns an array of strings with the matches highlighted.
     *
     *  === Options
     *
     *  :excerpt_length::   Default: 150. Length of excerpt to show. Highlighted
     *                      terms will be in the centre of the excerpt. Set to
     *                      :all to highlight the entire field.
     *  :num_excerpts::     Default: 2. Number of excerpts to return.
     *  :pre_tag::          Default: "<b>". Tag to place to the left of the match.
     *                      You'll probably want to change this to a "<span>" tag
     *                      with a class. Try "\033[7m" for use in a terminal.
     *  :post_tag::         Default: "</b>". This tag should close the +:pre_tag+.
     *                      Try tag "\033[m" in the terminal.
     *  :ellipsis::         Default: "...". This is the string that is appended at
     *                      the beginning and end of excerpts (unless the excerpt
     *                      hits the start or end of the field. You'll probably
     *                      want to change this so a Unicode ellipsis character.
     */
    static VALUE
    frt_sea_highlight(int argc, VALUE *argv, VALUE self)
    {
        GET_SEA();
        VALUE rquery, rdoc_id, rfield, roptions, v;
        Query *query;
        int excerpt_length = 150;
        int num_excerpts = 2;
        char *pre_tag = "<b>";
        char *post_tag = "</b>";
        char *ellipsis = "...";
        char **excerpts;

        rb_scan_args(argc, argv, "31", &rquery, &rdoc_id, &rfield, &roptions);
        Data_Get_Struct(rquery, Query, query);
        if (argc > 3) {
            if (TYPE(roptions) != T_HASH) {
               rb_raise(rb_eArgError, "The fourth argument to Searcher#highlight must be a hash");
            }
            if (Qnil != (v = rb_hash_aref(roptions, sym_num_excerpts))) {
                num_excerpts =  FIX2INT(v);
            }
            if (Qnil != (v = rb_hash_aref(roptions, sym_excerpt_length))) {
                if (v == sym_all) {
                    num_excerpts = 1;
                    excerpt_length = INT_MAX/2;
                }
                else {
                    excerpt_length = FIX2INT(v);
                }
            }
            if (Qnil != (v = rb_hash_aref(roptions, sym_pre_tag))) {
                pre_tag = rs2s(rb_obj_as_string(v));
            }
            if (Qnil != (v = rb_hash_aref(roptions, sym_post_tag))) {
                post_tag = rs2s(rb_obj_as_string(v));
            }
            if (Qnil != (v = rb_hash_aref(roptions, sym_ellipsis))) {
                ellipsis = rs2s(rb_obj_as_string(v));
            }
        }

        if ((excerpts = searcher_highlight(sea,
                                           query,
                                           FIX2INT(rdoc_id),
                                           frt_field(rfield),
                                           excerpt_length,
                                           num_excerpts,
                                           pre_tag,
                                           post_tag,
                                           ellipsis)) != NULL) {
            const int size = ary_size(excerpts);
            int i;
            VALUE rexcerpts = rb_ary_new2(size);

            for (i = 0; i < size; i++) {
                RARRAY(rexcerpts)->ptr[i] = rb_str_new2(excerpts[i]);
                RARRAY(rexcerpts)->len++;
            }
            ary_destroy(excerpts, &free);
            return rexcerpts;
        }
        return Qnil;
    }