Add ability to pipe output from calls

This commit is contained in:
Přemysl Eric Janouch 2016-01-21 09:26:29 +01:00
parent e70cd4e434
commit 46b926d9e5
1 changed files with 51 additions and 22 deletions

View File

@ -2706,6 +2706,22 @@ quit (struct app_context *ctx)
ctx->input->vtable->hide (ctx->input); ctx->input->vtable->hide (ctx->input);
} }
static void
suspend_terminal (struct app_context *ctx)
{
ctx->input->vtable->hide (ctx->input);
ev_io_stop (EV_DEFAULT_ &ctx->tty_watcher);
ctx->input->vtable->prepare (ctx->input, false);
}
static void
resume_terminal (struct app_context *ctx)
{
ctx->input->vtable->prepare (ctx->input, true);
ev_io_start (EV_DEFAULT_ &ctx->tty_watcher);
ctx->input->vtable->show (ctx->input);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
#define PARSE_FAIL(...) \ #define PARSE_FAIL(...) \
@ -2714,8 +2730,28 @@ quit (struct app_context *ctx)
goto fail; \ goto fail; \
BLOCK_END BLOCK_END
// XXX: should probably rather defer this action and use spawn_helper_child()
static void
display_via_pipeline (struct app_context *ctx,
const char *s, const char *pipeline)
{
suspend_terminal (ctx);
errno = 0;
FILE *fp = popen (pipeline, "w");
if (fp)
{
fputs (s, fp);
pclose (fp);
}
if (errno)
print_error ("pipeline failed: %s", strerror (errno));
resume_terminal (ctx);
}
static bool static bool
parse_response (struct app_context *ctx, struct str *buf) parse_response (struct app_context *ctx, struct str *buf, const char *pipeline)
{ {
json_error_t e; json_error_t e;
json_t *response; json_t *response;
@ -2803,6 +2839,8 @@ parse_response (struct app_context *ctx, struct str *buf)
if (!s) if (!s)
print_error ("character conversion failed for `%s'", "result"); print_error ("character conversion failed for `%s'", "result");
else if (pipeline)
display_via_pipeline (ctx, s, pipeline);
else else
{ {
json_highlight (ctx, s, stdout); json_highlight (ctx, s, stdout);
@ -2832,7 +2870,7 @@ is_valid_json_rpc_params (json_t *v)
static void static void
make_json_rpc_call (struct app_context *ctx, make_json_rpc_call (struct app_context *ctx,
const char *method, json_t *id, json_t *params) const char *method, json_t *id, json_t *params, const char *pipeline)
{ {
json_t *request = json_object (); json_t *request = json_object ();
json_object_set_new (request, "jsonrpc", json_string ("2.0")); json_object_set_new (request, "jsonrpc", json_string ("2.0"));
@ -2867,7 +2905,7 @@ make_json_rpc_call (struct app_context *ctx,
bool success = false; bool success = false;
if (id) if (id)
success = parse_response (ctx, &buf); success = parse_response (ctx, &buf, pipeline);
else else
{ {
printf ("[Notification]\n"); printf ("[Notification]\n");
@ -2933,6 +2971,7 @@ process_input (char *user_input, void *user_data)
size_t args_len = 0; size_t args_len = 0;
json_t *args[2] = { NULL, NULL }, *id = NULL, *params = NULL; json_t *args[2] = { NULL, NULL }, *id = NULL, *params = NULL;
char *pipeline = NULL;
while (true) while (true)
{ {
// Jansson is too stupid to just tell us that there was nothing; // Jansson is too stupid to just tell us that there was nothing;
@ -2942,6 +2981,12 @@ process_input (char *user_input, void *user_data)
if (!*p) if (!*p)
break; break;
if (*p == '|')
{
pipeline = xstrdup (++p);
break;
}
if (args_len == N_ELEMENTS (args)) if (args_len == N_ELEMENTS (args))
{ {
print_error ("too many arguments"); print_error ("too many arguments");
@ -2981,9 +3026,11 @@ process_input (char *user_input, void *user_data)
if (!id && ctx->auto_id) if (!id && ctx->auto_id)
id = json_integer (ctx->next_id++); id = json_integer (ctx->next_id++);
make_json_rpc_call (ctx, method, id, params); make_json_rpc_call (ctx, method, id, params, pipeline);
fail_parse: fail_parse:
free (pipeline);
if (id) json_decref (id); if (id) json_decref (id);
if (params) json_decref (params); if (params) json_decref (params);
@ -2998,24 +3045,6 @@ fail:
// The ability to use an external editor on the input line has been shamelessly // The ability to use an external editor on the input line has been shamelessly
// copypasted from degesch with minor changes only. // copypasted from degesch with minor changes only.
static void
suspend_terminal (struct app_context *ctx)
{
ctx->input->vtable->hide (ctx->input);
ev_io_stop (EV_DEFAULT_ &ctx->tty_watcher);
ctx->input->vtable->prepare (ctx->input, false);
}
static void
resume_terminal (struct app_context *ctx)
{
ctx->input->vtable->prepare (ctx->input, true);
ev_io_start (EV_DEFAULT_ &ctx->tty_watcher);
ctx->input->vtable->show (ctx->input);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/// This differs from the non-unique version in that we expect the filename /// This differs from the non-unique version in that we expect the filename
/// to be something like a pattern for mkstemp(), so the resulting path can /// to be something like a pattern for mkstemp(), so the resulting path can
/// reside in a system-wide directory with no risk of a conflict. /// reside in a system-wide directory with no risk of a conflict.