Kouhei Sutou
null+****@clear*****
Mon Nov 23 16:44:40 JST 2015
Kouhei Sutou 2015-11-23 16:44:40 +0900 (Mon, 23 Nov 2015) New Revision: ddb0d0998b0df06cf44cff2853ce159e4935ef97 https://github.com/groonga/groonga/commit/ddb0d0998b0df06cf44cff2853ce159e4935ef97 Message: Support pretty print for JSON output For example: `table_list --pretty yes` Modified files: lib/ctx.c lib/grn_ctx_impl.h lib/output.c Modified: lib/ctx.c (+23 -0) =================================================================== --- lib/ctx.c 2015-11-23 15:44:48 +0900 (1be1bd4) +++ lib/ctx.c 2015-11-23 16:44:40 +0900 (a894215) @@ -1362,10 +1362,12 @@ get_command_version(grn_ctx *ctx, const char *p, const char *pe) #define OUTPUT_TYPE "output_type" #define COMMAND_VERSION "command_version" #define REQUEST_ID "request_id" +#define PRETTY "pretty" #define EXPR_MISSING "expr_missing" #define OUTPUT_TYPE_LEN (sizeof(OUTPUT_TYPE) - 1) #define COMMAND_VERSION_LEN (sizeof(COMMAND_VERSION) - 1) #define REQUEST_ID_LEN (sizeof(REQUEST_ID) - 1) +#define PRETTY_LEN (sizeof(PRETTY) - 1) #define HTTP_QUERY_PAIR_DELIMITER "=" #define HTTP_QUERY_PAIRS_DELIMITERS "&;" @@ -1417,6 +1419,16 @@ grn_ctx_qe_exec_uri(grn_ctx *ctx, const char *path, uint32_t path_len) p = grn_text_cgidec(ctx, &request_id, p, e, HTTP_QUERY_PAIRS_DELIMITERS); if (ctx->rc) { goto exit; } + } else if (l == PRETTY_LEN && + !memcmp(v, PRETTY, PRETTY_LEN)) { + GRN_BULK_REWIND(&buf); + p = grn_text_cgidec(ctx, &buf, p, e, HTTP_QUERY_PAIRS_DELIMITERS); + if (GRN_TEXT_LEN(&buf) == strlen("yes") && + !memcmp(GRN_TEXT_VALUE(&buf), "yes", GRN_TEXT_LEN(&buf))) { + ctx->impl->output.is_pretty = GRN_TRUE; + } else { + ctx->impl->output.is_pretty = GRN_FALSE; + } } else { if (!(val = grn_expr_get_or_add_var(ctx, expr, v, l))) { val = &buf; @@ -1496,6 +1508,16 @@ grn_ctx_qe_exec(grn_ctx *ctx, const char *str, uint32_t str_len) GRN_BULK_REWIND(&request_id); p = grn_text_unesc_tok(ctx, &request_id, p, e, &tok_type); if (ctx->rc) { goto exit; } + } else if (l == PRETTY_LEN && + !memcmp(v, PRETTY, PRETTY_LEN)) { + GRN_BULK_REWIND(&buf); + p = grn_text_unesc_tok(ctx, &buf, p, e, &tok_type); + if (GRN_TEXT_LEN(&buf) == strlen("yes") && + !memcmp(GRN_TEXT_VALUE(&buf), "yes", GRN_TEXT_LEN(&buf))) { + ctx->impl->output.is_pretty = GRN_TRUE; + } else { + ctx->impl->output.is_pretty = GRN_FALSE; + } } else if (expr && (val = grn_expr_get_or_add_var(ctx, expr, v, l))) { grn_obj_reinit(ctx, val, GRN_DB_TEXT, 0); p = grn_text_unesc_tok(ctx, val, p, e, &tok_type); @@ -1619,6 +1641,7 @@ grn_ctx_send(grn_ctx *ctx, const char *str, unsigned int str_len, int flags) if (comment_command_p(str, str_len)) { goto output; }; ctx->impl->output.type = GRN_CONTENT_JSON; ctx->impl->output.mime_type = "application/json"; + ctx->impl->output.is_pretty = GRN_FALSE; grn_timeval_now(ctx, &ctx->impl->tv); GRN_QUERY_LOG(ctx, GRN_QUERY_LOG_COMMAND, ">", "%.*s", str_len, str); Modified: lib/grn_ctx_impl.h (+1 -0) =================================================================== --- lib/grn_ctx_impl.h 2015-11-23 15:44:48 +0900 (2f4e7f3) +++ lib/grn_ctx_impl.h 2015-11-23 16:44:40 +0900 (6670d18) @@ -166,6 +166,7 @@ struct _grn_ctx_impl { } data; grn_content_type type; const char *mime_type; + grn_bool is_pretty; grn_obj names; grn_obj levels; #ifdef GRN_WITH_MESSAGE_PACK Modified: lib/output.c (+109 -11) =================================================================== --- lib/output.c 2015-11-23 15:44:48 +0900 (e398e3e) +++ lib/output.c 2015-11-23 16:44:40 +0900 (158ea3a) @@ -32,13 +32,30 @@ #define INCR_LENGTH (DEPTH ? (GRN_UINT32_VALUE_AT(LEVELS, (DEPTH - 1)) += 2) : 0) static void +indent(grn_ctx *ctx, grn_obj *outbuf, int level) +{ + int i; + for (i = 0; i < level; i++) { + GRN_TEXT_PUTS(ctx, outbuf, " "); + } +} + +static void put_delimiter(grn_ctx *ctx, grn_obj *outbuf, grn_content_type output_type) { uint32_t level = CURR_LEVEL; switch (output_type) { case GRN_CONTENT_JSON: if (level < 2) { return; } - GRN_TEXT_PUTC(ctx, outbuf, ((level & 3) == 3) ? ':' : ','); + if ((level & 3) == 3) { + GRN_TEXT_PUTC(ctx, outbuf, ':'); + } else { + GRN_TEXT_PUTC(ctx, outbuf, ','); + if (ctx->impl->output.is_pretty) { + GRN_TEXT_PUTC(ctx, outbuf, '\n'); + indent(ctx, outbuf, DEPTH); + } + } // if (DEPTH == 1 && ((level & 3) != 3)) { GRN_TEXT_PUTC(ctx, outbuf, '\n'); } break; case GRN_CONTENT_XML: @@ -70,6 +87,10 @@ grn_output_array_open(grn_ctx *ctx, grn_obj *outbuf, grn_content_type output_typ switch (output_type) { case GRN_CONTENT_JSON: GRN_TEXT_PUTC(ctx, outbuf, '['); + if (ctx->impl->output.is_pretty) { + GRN_TEXT_PUTC(ctx, outbuf, '\n'); + indent(ctx, outbuf, DEPTH + 1); + } break; case GRN_CONTENT_XML: GRN_TEXT_PUTC(ctx, outbuf, '<'); @@ -107,6 +128,10 @@ grn_output_array_close(grn_ctx *ctx, grn_obj *outbuf, grn_content_type output_ty { switch (output_type) { case GRN_CONTENT_JSON: + if (ctx->impl->output.is_pretty) { + GRN_TEXT_PUTC(ctx, outbuf, '\n'); + indent(ctx, outbuf, DEPTH - 1); + } GRN_TEXT_PUTC(ctx, outbuf, ']'); break; case GRN_CONTENT_TSV: @@ -1848,39 +1873,112 @@ grn_output_envelope(grn_ctx *ctx, GRN_TEXT_PUT(ctx, head, GRN_TEXT_VALUE(jsonp_func), GRN_TEXT_LEN(jsonp_func)); GRN_TEXT_PUTC(ctx, head, '('); } - GRN_TEXT_PUTS(ctx, head, "[["); - grn_text_itoa(ctx, head, rc); - GRN_TEXT_PUTC(ctx, head, ','); - grn_text_ftoa(ctx, head, started); - GRN_TEXT_PUTC(ctx, head, ','); - grn_text_ftoa(ctx, head, elapsed); + if (ctx->impl->output.is_pretty) { + grn_text_printf(ctx, head, + "[\n" + "[\n" + " %d,\n" + " %f,\n" + " %f", + rc, started, elapsed); + } else { + grn_text_printf(ctx, head, + "[[%d,%f,%f", + rc, started, elapsed); + } if (rc != GRN_SUCCESS) { GRN_TEXT_PUTC(ctx, head, ','); + if (ctx->impl->output.is_pretty) { + GRN_TEXT_PUTS(ctx, head, + "\n" + " "); + } grn_text_esc(ctx, head, ctx->errbuf, strlen(ctx->errbuf)); if (ctx->errfunc && ctx->errfile) { grn_obj *command; - /* TODO: output backtrace */ - GRN_TEXT_PUTS(ctx, head, ",[["); + if (ctx->impl->output.is_pretty) { + GRN_TEXT_PUTS(ctx, head, + ",\n" + " [\n" + " [\n" + " "); + } else { + GRN_TEXT_PUTS(ctx, head, ",[["); + } grn_text_esc(ctx, head, ctx->errfunc, strlen(ctx->errfunc)); GRN_TEXT_PUTC(ctx, head, ','); + if (ctx->impl->output.is_pretty) { + GRN_TEXT_PUTS(ctx, head, + "\n" + " "); + } grn_text_esc(ctx, head, ctx->errfile, strlen(ctx->errfile)); GRN_TEXT_PUTC(ctx, head, ','); + if (ctx->impl->output.is_pretty) { + GRN_TEXT_PUTS(ctx, head, + "\n" + " "); + } grn_text_itoa(ctx, head, ctx->errline); + if (ctx->impl->output.is_pretty) { + GRN_TEXT_PUTS(ctx, head, + "\n" + " "); + } GRN_TEXT_PUTS(ctx, head, "]"); if (file && (command = GRN_CTX_USER_DATA(ctx)->ptr)) { - GRN_TEXT_PUTS(ctx, head, ",["); + if (ctx->impl->output.is_pretty) { + GRN_TEXT_PUTS(ctx, head, + ",\n" + " [\n" + " "); + } else { + GRN_TEXT_PUTS(ctx, head, ",["); + } grn_text_esc(ctx, head, file, strlen(file)); GRN_TEXT_PUTC(ctx, head, ','); + if (ctx->impl->output.is_pretty) { + GRN_TEXT_PUTS(ctx, head, + "\n" + " "); + } grn_text_itoa(ctx, head, line); GRN_TEXT_PUTC(ctx, head, ','); + if (ctx->impl->output.is_pretty) { + GRN_TEXT_PUTS(ctx, head, + "\n" + " "); + } grn_text_esc(ctx, head, GRN_TEXT_VALUE(command), GRN_TEXT_LEN(command)); + if (ctx->impl->output.is_pretty) { + GRN_TEXT_PUTS(ctx, head, + "\n" + " "); + } GRN_TEXT_PUTS(ctx, head, "]"); } + if (ctx->impl->output.is_pretty) { + GRN_TEXT_PUTS(ctx, head, + "\n" + " "); + } GRN_TEXT_PUTS(ctx, head, "]"); } } + if (ctx->impl->output.is_pretty) { + GRN_TEXT_PUTC(ctx, head, '\n'); + } GRN_TEXT_PUTC(ctx, head, ']'); - if (GRN_TEXT_LEN(body)) { GRN_TEXT_PUTC(ctx, head, ','); } + if (GRN_TEXT_LEN(body)) { + GRN_TEXT_PUTC(ctx, head, ','); + if (ctx->impl->output.is_pretty) { + GRN_TEXT_PUTC(ctx, head, '\n'); + } + } + + if (ctx->impl->output.is_pretty) { + GRN_TEXT_PUTS(ctx, foot, "\n"); + } GRN_TEXT_PUTC(ctx, foot, ']'); if (jsonp_func && GRN_TEXT_LEN(jsonp_func)) { GRN_TEXT_PUTS(ctx, foot, ");"); -------------- next part -------------- HTML����������������������������...Download