From 5009d628a3b1c800404b1a59ef0a935639260a87 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Mon, 8 Apr 2019 19:28:44 +0930 Subject: [PATCH] lightning-cli: do pretty-printing. Plugins don't do it right anyway, and we're about to remove it from lightningd. Produces same format as json_pp. Signed-off-by: Rusty Russell --- cli/lightning-cli.c | 81 +++++++++++++++++++++++++++++++++++++++-- doc/lightning-cli.1 | 9 ++++- doc/lightning-cli.1.txt | 2 + tests/test_plugin.py | 2 +- tools/bench-gossipd.sh | 2 +- 5 files changed, 88 insertions(+), 8 deletions(-) diff --git a/cli/lightning-cli.c b/cli/lightning-cli.c index 1ef55e178..73a14ec82 100644 --- a/cli/lightning-cli.c +++ b/cli/lightning-cli.c @@ -114,7 +114,8 @@ static void human_help(const char *buffer, const jsmntok_t *result, bool has_com enum format { JSON, HUMAN, - DEFAULT_FORMAT + DEFAULT_FORMAT, + RAW }; static char *opt_set_human(enum format *format) @@ -129,6 +130,12 @@ static char *opt_set_json(enum format *format) return NULL; } +static char *opt_set_raw(enum format *format) +{ + *format = RAW; + return NULL; +} + enum input { KEYWORDS, ORDERED, @@ -202,6 +209,61 @@ try_exec_man (const char *page, char *relative_to) { exit(0); } +static void print_json(const char *str, const jsmntok_t *tok, const char *indent) +{ + size_t i; + const jsmntok_t *t; + bool first; + char next_indent[strlen(indent) + 3 + 1]; + + memset(next_indent, ' ', sizeof(next_indent)-1); + next_indent[sizeof(next_indent)-1] = '\0'; + + switch (tok->type) { + case JSMN_PRIMITIVE: + case JSMN_STRING: + printf("%.*s", json_tok_full_len(tok), json_tok_full(str, tok)); + return; + + case JSMN_ARRAY: + first = true; + json_for_each_arr(i, t, tok) { + if (first) + printf("[\n%s", next_indent); + else + printf(",\n%s", next_indent); + print_json(str, t, next_indent); + first = false; + } + if (first) + printf("[]"); + else + printf("\n%s]", indent); + return; + + case JSMN_OBJECT: + first = true; + json_for_each_obj(i, t, tok) { + if (first) + printf("{\n%s", next_indent); + else + printf(",\n%s", next_indent); + print_json(str, t, next_indent); + printf(" : "); + print_json(str, t + 1, next_indent); + first = false; + } + if (first) + printf("{}"); + else + printf("\n%s}", indent); + return; + case JSMN_UNDEFINED: + break; + } + abort(); +} + int main(int argc, char *argv[]) { setup_locale(); @@ -232,6 +294,8 @@ int main(int argc, char *argv[]) "Human-readable output (default for 'help')"); opt_register_noarg("-J|--json", opt_set_json, &format, "JSON output (default unless 'help')"); + opt_register_noarg("-R|--raw", opt_set_raw, &format, + "Raw, unformatted JSON output"); opt_register_noarg("-k|--keywords", opt_set_keywords, &input, "Use format key=value for "); opt_register_noarg("-o|--order", opt_set_ordered, &input, @@ -387,10 +451,14 @@ int main(int argc, char *argv[]) human_help(resp, result, false); else human_readable(resp, result, '\n'); - else + else if (format == RAW) printf("%.*s\n", json_tok_full_len(result), json_tok_full(resp, result)); + else { + print_json(resp, result, ""); + printf("\n"); + } tal_free(lightning_dir); tal_free(rpc_filename); tal_free(ctx); @@ -398,8 +466,13 @@ int main(int argc, char *argv[]) return 0; } - printf("%.*s\n", - json_tok_full_len(error), json_tok_full(resp, error)); + if (format == RAW) + printf("%.*s\n", + json_tok_full_len(error), json_tok_full(resp, error)); + else { + print_json(resp, error, ""); + printf("\n"); + } tal_free(lightning_dir); tal_free(rpc_filename); tal_free(ctx); diff --git a/doc/lightning-cli.1 b/doc/lightning-cli.1 index 652487ac6..abd7a3b87 100644 --- a/doc/lightning-cli.1 +++ b/doc/lightning-cli.1 @@ -2,12 +2,12 @@ .\" Title: lightning-cli .\" Author: [see the "AUTHOR" section] .\" Generator: DocBook XSL Stylesheets v1.79.1 -.\" Date: 02/11/2018 +.\" Date: 04/02/2019 .\" Manual: \ \& .\" Source: \ \& .\" Language: English .\" -.TH "LIGHTNING\-CLI" "1" "02/11/2018" "\ \&" "\ \&" +.TH "LIGHTNING\-CLI" "1" "04/02/2019" "\ \&" "\ \&" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -69,6 +69,11 @@ Return result in JSON format (default unless command) .RE .PP +\fB\-\-raw\fR/\fB\-R\fR +.RS 4 +Return raw JSON directly as lightningd replies +.RE +.PP \fB\-\-human\-readable\fR/\fB\-H\fR .RS 4 Return result in human\-readable output (default for diff --git a/doc/lightning-cli.1.txt b/doc/lightning-cli.1.txt index 371959e3d..e697fd7e1 100644 --- a/doc/lightning-cli.1.txt +++ b/doc/lightning-cli.1.txt @@ -29,6 +29,8 @@ OPTIONS Follow strictly the order of parameters for the command *--json*/*-J*:: Return result in JSON format (default unless 'help' command) +*--raw*/*-R*:: + Return raw JSON directly as lightningd replies *--human-readable*/*-H*:: Return result in human-readable output (default for 'help' command) *--help*/*-h*:: diff --git a/tests/test_plugin.py b/tests/test_plugin.py index d6074d1c7..ebba4bde8 100644 --- a/tests/test_plugin.py +++ b/tests/test_plugin.py @@ -232,4 +232,4 @@ def test_utf8_passthrough(node_factory, executor): .format(l1.daemon.lightning_dir), 'utf8', 'ナンセンス 1杯']).decode('utf-8') assert '\\u' not in out - assert out == '{"utf8": "ナンセンス 1杯"}\n' + assert out == '{\n "utf8" : "ナンセンス 1杯"\n}\n' diff --git a/tools/bench-gossipd.sh b/tools/bench-gossipd.sh index b3b45cffa..eecc9ad05 100755 --- a/tools/bench-gossipd.sh +++ b/tools/bench-gossipd.sh @@ -76,7 +76,7 @@ if ! bitcoin-cli -regtest ping >/dev/null 2>&1; then fi LIGHTNINGD="./lightningd/lightningd --network=regtest --dev-gossip-time=1550513768 --dev-unknown-channel-satoshis=100000" -LCLI1="./cli/lightning-cli --lightning-dir=$DIR" +LCLI1="./cli/lightning-cli --lightning-dir=$DIR -R" if [ -z "$DIR" ]; then trap 'rm -rf "$DIR"' 0