Send proper error messages upon parser failures, use yajl for generating command replies
Fixes: #693
This commit is contained in:
parent
87cb664236
commit
bbe607899c
|
@ -35,6 +35,9 @@
|
||||||
#include <xcb/xcb_keysyms.h>
|
#include <xcb/xcb_keysyms.h>
|
||||||
#include <xcb/xcb_icccm.h>
|
#include <xcb/xcb_icccm.h>
|
||||||
|
|
||||||
|
#include <yajl/yajl_gen.h>
|
||||||
|
#include <yajl/yajl_version.h>
|
||||||
|
|
||||||
/* Contains compatibility definitions for old libxcb versions */
|
/* Contains compatibility definitions for old libxcb versions */
|
||||||
#ifdef XCB_COMPAT
|
#ifdef XCB_COMPAT
|
||||||
#include "xcb_compat.h"
|
#include "xcb_compat.h"
|
||||||
|
|
|
@ -10,6 +10,8 @@
|
||||||
#ifndef _COMMANDS_PARSER_H
|
#ifndef _COMMANDS_PARSER_H
|
||||||
#define _COMMANDS_PARSER_H
|
#define _COMMANDS_PARSER_H
|
||||||
|
|
||||||
|
#include <yajl/yajl_gen.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Holds the result of a call to any command. When calling
|
* Holds the result of a call to any command. When calling
|
||||||
* parse_command("floating enable, border none"), the parser will internally
|
* parse_command("floating enable, border none"), the parser will internally
|
||||||
|
@ -20,8 +22,8 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
struct CommandResult {
|
struct CommandResult {
|
||||||
/* The JSON-serialized output of this command. */
|
/* The JSON generator to append a reply to. */
|
||||||
char *json_output;
|
yajl_gen json_gen;
|
||||||
|
|
||||||
/* Whether the command requires calling tree_render. */
|
/* Whether the command requires calling tree_render. */
|
||||||
bool needs_tree_render;
|
bool needs_tree_render;
|
||||||
|
|
|
@ -49,7 +49,7 @@ void run_assignments(i3Window *window) {
|
||||||
if (command_output->needs_tree_render)
|
if (command_output->needs_tree_render)
|
||||||
needs_tree_render = true;
|
needs_tree_render = true;
|
||||||
|
|
||||||
free(command_output->json_output);
|
yajl_gen_free(command_output->json_gen);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Store that we ran this assignment to not execute it again */
|
/* Store that we ran this assignment to not execute it again */
|
||||||
|
|
217
src/commands.c
217
src/commands.c
|
@ -12,6 +12,16 @@
|
||||||
|
|
||||||
#include "all.h"
|
#include "all.h"
|
||||||
|
|
||||||
|
// Macros to make the YAJL API a bit easier to use.
|
||||||
|
#define y(x, ...) yajl_gen_ ## x (cmd_output->json_gen, ##__VA_ARGS__)
|
||||||
|
#define ystr(str) yajl_gen_string(cmd_output->json_gen, (unsigned char*)str, strlen(str))
|
||||||
|
#define ysuccess(success) do { \
|
||||||
|
y(map_open); \
|
||||||
|
ystr("success"); \
|
||||||
|
y(bool, success); \
|
||||||
|
y(map_close); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
/** When the command did not include match criteria (!), we use the currently
|
/** When the command did not include match criteria (!), we use the currently
|
||||||
* focused command. Do not confuse this case with a command which included
|
* focused command. Do not confuse this case with a command which included
|
||||||
* criteria but which did not match any windows. This macro has to be called in
|
* criteria but which did not match any windows. This macro has to be called in
|
||||||
|
@ -341,7 +351,7 @@ void cmd_move_con_to_workspace(I3_CMD, char *which) {
|
||||||
ws = workspace_prev_on_output();
|
ws = workspace_prev_on_output();
|
||||||
else {
|
else {
|
||||||
ELOG("BUG: called with which=%s\n", which);
|
ELOG("BUG: called with which=%s\n", which);
|
||||||
cmd_output->json_output = sstrdup("{\"success\": false}");
|
ysuccess(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -352,7 +362,7 @@ void cmd_move_con_to_workspace(I3_CMD, char *which) {
|
||||||
|
|
||||||
cmd_output->needs_tree_render = true;
|
cmd_output->needs_tree_render = true;
|
||||||
// XXX: default reply for now, make this a better reply
|
// XXX: default reply for now, make this a better reply
|
||||||
cmd_output->json_output = sstrdup("{\"success\": true}");
|
ysuccess(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -362,7 +372,7 @@ void cmd_move_con_to_workspace(I3_CMD, char *which) {
|
||||||
void cmd_move_con_to_workspace_name(I3_CMD, char *name) {
|
void cmd_move_con_to_workspace_name(I3_CMD, char *name) {
|
||||||
if (strncasecmp(name, "__i3_", strlen("__i3_")) == 0) {
|
if (strncasecmp(name, "__i3_", strlen("__i3_")) == 0) {
|
||||||
LOG("You cannot switch to the i3 internal workspaces.\n");
|
LOG("You cannot switch to the i3 internal workspaces.\n");
|
||||||
cmd_output->json_output = sstrdup("{\"success\": false}");
|
ysuccess(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -371,7 +381,7 @@ void cmd_move_con_to_workspace_name(I3_CMD, char *name) {
|
||||||
/* Error out early to not create a non-existing workspace (in
|
/* Error out early to not create a non-existing workspace (in
|
||||||
* workspace_get()) if we are not actually able to move anything. */
|
* workspace_get()) if we are not actually able to move anything. */
|
||||||
if (match_is_empty(current_match) && focused->type == CT_WORKSPACE) {
|
if (match_is_empty(current_match) && focused->type == CT_WORKSPACE) {
|
||||||
cmd_output->json_output = sstrdup("{\"success\": false}");
|
ysuccess(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -388,7 +398,7 @@ void cmd_move_con_to_workspace_name(I3_CMD, char *name) {
|
||||||
|
|
||||||
cmd_output->needs_tree_render = true;
|
cmd_output->needs_tree_render = true;
|
||||||
// XXX: default reply for now, make this a better reply
|
// XXX: default reply for now, make this a better reply
|
||||||
cmd_output->json_output = sstrdup("{\"success\": true}");
|
ysuccess(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -401,7 +411,7 @@ void cmd_move_con_to_workspace_number(I3_CMD, char *which) {
|
||||||
/* Error out early to not create a non-existing workspace (in
|
/* Error out early to not create a non-existing workspace (in
|
||||||
* workspace_get()) if we are not actually able to move anything. */
|
* workspace_get()) if we are not actually able to move anything. */
|
||||||
if (match_is_empty(current_match) && focused->type == CT_WORKSPACE) {
|
if (match_is_empty(current_match) && focused->type == CT_WORKSPACE) {
|
||||||
cmd_output->json_output = sstrdup("{\"success\": false}");
|
ysuccess(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -416,8 +426,13 @@ void cmd_move_con_to_workspace_number(I3_CMD, char *which) {
|
||||||
parsed_num < 0 ||
|
parsed_num < 0 ||
|
||||||
*endptr != '\0') {
|
*endptr != '\0') {
|
||||||
LOG("Could not parse \"%s\" as a number.\n", which);
|
LOG("Could not parse \"%s\" as a number.\n", which);
|
||||||
cmd_output->json_output = sstrdup("{\"success\": false, "
|
y(map_open);
|
||||||
"\"error\": \"Could not parse number\"}");
|
ystr("success");
|
||||||
|
y(bool, false);
|
||||||
|
ystr("error");
|
||||||
|
// TODO: better error message
|
||||||
|
ystr("Could not parse number");
|
||||||
|
y(map_close);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -426,8 +441,13 @@ void cmd_move_con_to_workspace_number(I3_CMD, char *which) {
|
||||||
child->num == parsed_num);
|
child->num == parsed_num);
|
||||||
|
|
||||||
if (!workspace) {
|
if (!workspace) {
|
||||||
cmd_output->json_output = sstrdup("{\"success\": false, "
|
y(map_open);
|
||||||
"\"error\": \"No such workspace\"}");
|
ystr("success");
|
||||||
|
y(bool, false);
|
||||||
|
ystr("error");
|
||||||
|
// TODO: better error message
|
||||||
|
ystr("No such workspace");
|
||||||
|
y(map_close);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -440,7 +460,7 @@ void cmd_move_con_to_workspace_number(I3_CMD, char *which) {
|
||||||
|
|
||||||
cmd_output->needs_tree_render = true;
|
cmd_output->needs_tree_render = true;
|
||||||
// XXX: default reply for now, make this a better reply
|
// XXX: default reply for now, make this a better reply
|
||||||
cmd_output->json_output = sstrdup("{\"success\": true}");
|
ysuccess(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cmd_resize_floating(I3_CMD, char *way, char *direction, Con *floating_con, int px) {
|
static void cmd_resize_floating(I3_CMD, char *way, char *direction, Con *floating_con, int px) {
|
||||||
|
@ -490,7 +510,7 @@ static void cmd_resize_tiling_direction(I3_CMD, char *way, char *direction, int
|
||||||
(strcmp(direction, "left") == 0 || strcmp(direction, "right") == 0))) {
|
(strcmp(direction, "left") == 0 || strcmp(direction, "right") == 0))) {
|
||||||
LOG("You cannot resize in that direction. Your focus is in a %s split container currently.\n",
|
LOG("You cannot resize in that direction. Your focus is in a %s split container currently.\n",
|
||||||
(orientation == HORIZ ? "horizontal" : "vertical"));
|
(orientation == HORIZ ? "horizontal" : "vertical"));
|
||||||
cmd_output->json_output = sstrdup("{\"success\": false}");
|
ysuccess(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -501,7 +521,7 @@ static void cmd_resize_tiling_direction(I3_CMD, char *way, char *direction, int
|
||||||
}
|
}
|
||||||
if (other == TAILQ_END(workspaces)) {
|
if (other == TAILQ_END(workspaces)) {
|
||||||
LOG("No other container in this direction found, cannot resize.\n");
|
LOG("No other container in this direction found, cannot resize.\n");
|
||||||
cmd_output->json_output = sstrdup("{\"success\": false}");
|
ysuccess(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
LOG("other->percent = %f\n", other->percent);
|
LOG("other->percent = %f\n", other->percent);
|
||||||
|
@ -558,13 +578,13 @@ static void cmd_resize_tiling_width_height(I3_CMD, char *way, char *direction, i
|
||||||
strcmp(direction, "width") == 0)) {
|
strcmp(direction, "width") == 0)) {
|
||||||
LOG("You cannot resize in that direction. Your focus is in a %s split container currently.\n",
|
LOG("You cannot resize in that direction. Your focus is in a %s split container currently.\n",
|
||||||
(orientation == HORIZ ? "horizontal" : "vertical"));
|
(orientation == HORIZ ? "horizontal" : "vertical"));
|
||||||
cmd_output->json_output = sstrdup("{\"success\": false}");
|
ysuccess(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (children == 1) {
|
if (children == 1) {
|
||||||
LOG("This is the only container, cannot resize.\n");
|
LOG("This is the only container, cannot resize.\n");
|
||||||
cmd_output->json_output = sstrdup("{\"success\": false}");
|
ysuccess(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -587,13 +607,13 @@ static void cmd_resize_tiling_width_height(I3_CMD, char *way, char *direction, i
|
||||||
continue;
|
continue;
|
||||||
if (!definitelyGreaterThan(child->percent - subtract_percent, 0.05, DBL_EPSILON)) {
|
if (!definitelyGreaterThan(child->percent - subtract_percent, 0.05, DBL_EPSILON)) {
|
||||||
LOG("Not resizing, already at minimum size (child %p would end up with a size of %.f\n", child, child->percent - subtract_percent);
|
LOG("Not resizing, already at minimum size (child %p would end up with a size of %.f\n", child, child->percent - subtract_percent);
|
||||||
cmd_output->json_output = sstrdup("{\"success\": false}");
|
ysuccess(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!definitelyGreaterThan(new_current_percent, 0.05, DBL_EPSILON)) {
|
if (!definitelyGreaterThan(new_current_percent, 0.05, DBL_EPSILON)) {
|
||||||
LOG("Not resizing, already at minimum size\n");
|
LOG("Not resizing, already at minimum size\n");
|
||||||
cmd_output->json_output = sstrdup("{\"success\": false}");
|
ysuccess(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -635,7 +655,7 @@ void cmd_resize(I3_CMD, char *way, char *direction, char *resize_px, char *resiz
|
||||||
|
|
||||||
cmd_output->needs_tree_render = true;
|
cmd_output->needs_tree_render = true;
|
||||||
// XXX: default reply for now, make this a better reply
|
// XXX: default reply for now, make this a better reply
|
||||||
cmd_output->json_output = sstrdup("{\"success\": true}");
|
ysuccess(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -663,7 +683,7 @@ void cmd_border(I3_CMD, char *border_style_str) {
|
||||||
border_style = BS_1PIXEL;
|
border_style = BS_1PIXEL;
|
||||||
else {
|
else {
|
||||||
ELOG("BUG: called with border_style=%s\n", border_style_str);
|
ELOG("BUG: called with border_style=%s\n", border_style_str);
|
||||||
cmd_output->json_output = sstrdup("{\"success\": false}");
|
ysuccess(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -672,7 +692,7 @@ void cmd_border(I3_CMD, char *border_style_str) {
|
||||||
|
|
||||||
cmd_output->needs_tree_render = true;
|
cmd_output->needs_tree_render = true;
|
||||||
// XXX: default reply for now, make this a better reply
|
// XXX: default reply for now, make this a better reply
|
||||||
cmd_output->json_output = sstrdup("{\"success\": true}");
|
ysuccess(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -695,7 +715,7 @@ void cmd_append_layout(I3_CMD, char *path) {
|
||||||
|
|
||||||
cmd_output->needs_tree_render = true;
|
cmd_output->needs_tree_render = true;
|
||||||
// XXX: default reply for now, make this a better reply
|
// XXX: default reply for now, make this a better reply
|
||||||
cmd_output->json_output = sstrdup("{\"success\": true}");
|
ysuccess(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -717,7 +737,7 @@ void cmd_workspace(I3_CMD, char *which) {
|
||||||
ws = workspace_prev_on_output();
|
ws = workspace_prev_on_output();
|
||||||
else {
|
else {
|
||||||
ELOG("BUG: called with which=%s\n", which);
|
ELOG("BUG: called with which=%s\n", which);
|
||||||
cmd_output->json_output = sstrdup("{\"success\": false}");
|
ysuccess(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -725,7 +745,7 @@ void cmd_workspace(I3_CMD, char *which) {
|
||||||
|
|
||||||
cmd_output->needs_tree_render = true;
|
cmd_output->needs_tree_render = true;
|
||||||
// XXX: default reply for now, make this a better reply
|
// XXX: default reply for now, make this a better reply
|
||||||
cmd_output->json_output = sstrdup("{\"success\": true}");
|
ysuccess(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -742,8 +762,14 @@ void cmd_workspace_number(I3_CMD, char *which) {
|
||||||
parsed_num < 0 ||
|
parsed_num < 0 ||
|
||||||
*endptr != '\0') {
|
*endptr != '\0') {
|
||||||
LOG("Could not parse \"%s\" as a number.\n", which);
|
LOG("Could not parse \"%s\" as a number.\n", which);
|
||||||
cmd_output->json_output = sstrdup("{\"success\": false, "
|
y(map_open);
|
||||||
"\"error\": \"Could not parse number\"}");
|
ystr("success");
|
||||||
|
y(bool, false);
|
||||||
|
ystr("error");
|
||||||
|
// TODO: better error message
|
||||||
|
ystr("Could not parse number");
|
||||||
|
y(map_close);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -753,8 +779,12 @@ void cmd_workspace_number(I3_CMD, char *which) {
|
||||||
|
|
||||||
if (!workspace) {
|
if (!workspace) {
|
||||||
LOG("There is no workspace with number %d.\n", parsed_num);
|
LOG("There is no workspace with number %d.\n", parsed_num);
|
||||||
cmd_output->json_output = sstrdup("{\"success\": false, "
|
y(map_open);
|
||||||
"\"error\": \"No such workspace\"}");
|
ystr("success");
|
||||||
|
y(bool, false);
|
||||||
|
ystr("error");
|
||||||
|
ystr("No such workspace");
|
||||||
|
y(map_close);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -762,7 +792,7 @@ void cmd_workspace_number(I3_CMD, char *which) {
|
||||||
|
|
||||||
cmd_output->needs_tree_render = true;
|
cmd_output->needs_tree_render = true;
|
||||||
// XXX: default reply for now, make this a better reply
|
// XXX: default reply for now, make this a better reply
|
||||||
cmd_output->json_output = sstrdup("{\"success\": true}");
|
ysuccess(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -774,7 +804,7 @@ void cmd_workspace_back_and_forth(I3_CMD) {
|
||||||
|
|
||||||
cmd_output->needs_tree_render = true;
|
cmd_output->needs_tree_render = true;
|
||||||
// XXX: default reply for now, make this a better reply
|
// XXX: default reply for now, make this a better reply
|
||||||
cmd_output->json_output = sstrdup("{\"success\": true}");
|
ysuccess(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -784,7 +814,7 @@ void cmd_workspace_back_and_forth(I3_CMD) {
|
||||||
void cmd_workspace_name(I3_CMD, char *name) {
|
void cmd_workspace_name(I3_CMD, char *name) {
|
||||||
if (strncasecmp(name, "__i3_", strlen("__i3_")) == 0) {
|
if (strncasecmp(name, "__i3_", strlen("__i3_")) == 0) {
|
||||||
LOG("You cannot switch to the i3 internal workspaces.\n");
|
LOG("You cannot switch to the i3 internal workspaces.\n");
|
||||||
cmd_output->json_output = sstrdup("{\"success\": false}");
|
ysuccess(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -799,7 +829,7 @@ void cmd_workspace_name(I3_CMD, char *name) {
|
||||||
workspace_back_and_forth();
|
workspace_back_and_forth();
|
||||||
tree_render();
|
tree_render();
|
||||||
}
|
}
|
||||||
cmd_output->json_output = sstrdup("{\"success\": false}");
|
ysuccess(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -807,7 +837,7 @@ void cmd_workspace_name(I3_CMD, char *name) {
|
||||||
|
|
||||||
cmd_output->needs_tree_render = true;
|
cmd_output->needs_tree_render = true;
|
||||||
// XXX: default reply for now, make this a better reply
|
// XXX: default reply for now, make this a better reply
|
||||||
cmd_output->json_output = sstrdup("{\"success\": true}");
|
ysuccess(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -835,7 +865,7 @@ void cmd_mark(I3_CMD, char *mark) {
|
||||||
|
|
||||||
cmd_output->needs_tree_render = true;
|
cmd_output->needs_tree_render = true;
|
||||||
// XXX: default reply for now, make this a better reply
|
// XXX: default reply for now, make this a better reply
|
||||||
cmd_output->json_output = sstrdup("{\"success\": true}");
|
ysuccess(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -847,7 +877,7 @@ void cmd_mode(I3_CMD, char *mode) {
|
||||||
switch_mode(mode);
|
switch_mode(mode);
|
||||||
|
|
||||||
// XXX: default reply for now, make this a better reply
|
// XXX: default reply for now, make this a better reply
|
||||||
cmd_output->json_output = sstrdup("{\"success\": true}");
|
ysuccess(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -885,7 +915,7 @@ void cmd_move_con_to_output(I3_CMD, char *name) {
|
||||||
|
|
||||||
if (!output) {
|
if (!output) {
|
||||||
LOG("No such output found.\n");
|
LOG("No such output found.\n");
|
||||||
cmd_output->json_output = sstrdup("{\"success\": false}");
|
ysuccess(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -893,7 +923,7 @@ void cmd_move_con_to_output(I3_CMD, char *name) {
|
||||||
Con *ws = NULL;
|
Con *ws = NULL;
|
||||||
GREP_FIRST(ws, output_get_content(output->con), workspace_is_visible(child));
|
GREP_FIRST(ws, output_get_content(output->con), workspace_is_visible(child));
|
||||||
if (!ws) {
|
if (!ws) {
|
||||||
cmd_output->json_output = sstrdup("{\"success\": false}");
|
ysuccess(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -904,7 +934,7 @@ void cmd_move_con_to_output(I3_CMD, char *name) {
|
||||||
|
|
||||||
cmd_output->needs_tree_render = true;
|
cmd_output->needs_tree_render = true;
|
||||||
// XXX: default reply for now, make this a better reply
|
// XXX: default reply for now, make this a better reply
|
||||||
cmd_output->json_output = sstrdup("{\"success\": true}");
|
ysuccess(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -935,7 +965,7 @@ void cmd_floating(I3_CMD, char *floating_mode) {
|
||||||
|
|
||||||
cmd_output->needs_tree_render = true;
|
cmd_output->needs_tree_render = true;
|
||||||
// XXX: default reply for now, make this a better reply
|
// XXX: default reply for now, make this a better reply
|
||||||
cmd_output->json_output = sstrdup("{\"success\": true}");
|
ysuccess(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -954,7 +984,7 @@ void cmd_move_workspace_to_output(I3_CMD, char *name) {
|
||||||
Output *output = get_output_from_string(current_output, name);
|
Output *output = get_output_from_string(current_output, name);
|
||||||
if (!output) {
|
if (!output) {
|
||||||
LOG("No such output\n");
|
LOG("No such output\n");
|
||||||
cmd_output->json_output = sstrdup("{\"success\": false}");
|
ysuccess(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1025,7 +1055,7 @@ void cmd_move_workspace_to_output(I3_CMD, char *name) {
|
||||||
|
|
||||||
cmd_output->needs_tree_render = true;
|
cmd_output->needs_tree_render = true;
|
||||||
// XXX: default reply for now, make this a better reply
|
// XXX: default reply for now, make this a better reply
|
||||||
cmd_output->json_output = sstrdup("{\"success\": true}");
|
ysuccess(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1039,7 +1069,7 @@ void cmd_split(I3_CMD, char *direction) {
|
||||||
|
|
||||||
cmd_output->needs_tree_render = true;
|
cmd_output->needs_tree_render = true;
|
||||||
// XXX: default reply for now, make this a better reply
|
// XXX: default reply for now, make this a better reply
|
||||||
cmd_output->json_output = sstrdup("{\"success\": true}");
|
ysuccess(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1060,7 +1090,7 @@ void cmd_kill(I3_CMD, char *kill_mode_str) {
|
||||||
kill_mode = KILL_CLIENT;
|
kill_mode = KILL_CLIENT;
|
||||||
else {
|
else {
|
||||||
ELOG("BUG: called with kill_mode=%s\n", kill_mode_str);
|
ELOG("BUG: called with kill_mode=%s\n", kill_mode_str);
|
||||||
cmd_output->json_output = sstrdup("{\"success\": false}");
|
ysuccess(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1076,7 +1106,7 @@ void cmd_kill(I3_CMD, char *kill_mode_str) {
|
||||||
|
|
||||||
cmd_output->needs_tree_render = true;
|
cmd_output->needs_tree_render = true;
|
||||||
// XXX: default reply for now, make this a better reply
|
// XXX: default reply for now, make this a better reply
|
||||||
cmd_output->json_output = sstrdup("{\"success\": true}");
|
ysuccess(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1090,7 +1120,7 @@ void cmd_exec(I3_CMD, char *nosn, char *command) {
|
||||||
start_application(command, no_startup_id);
|
start_application(command, no_startup_id);
|
||||||
|
|
||||||
// XXX: default reply for now, make this a better reply
|
// XXX: default reply for now, make this a better reply
|
||||||
cmd_output->json_output = sstrdup("{\"success\": true}");
|
ysuccess(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1102,7 +1132,7 @@ void cmd_focus_direction(I3_CMD, char *direction) {
|
||||||
focused->type != CT_WORKSPACE &&
|
focused->type != CT_WORKSPACE &&
|
||||||
focused->fullscreen_mode != CF_NONE) {
|
focused->fullscreen_mode != CF_NONE) {
|
||||||
LOG("Cannot change focus while in fullscreen mode.\n");
|
LOG("Cannot change focus while in fullscreen mode.\n");
|
||||||
cmd_output->json_output = sstrdup("{\"success\": false}");
|
ysuccess(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1118,13 +1148,13 @@ void cmd_focus_direction(I3_CMD, char *direction) {
|
||||||
tree_next('n', VERT);
|
tree_next('n', VERT);
|
||||||
else {
|
else {
|
||||||
ELOG("Invalid focus direction (%s)\n", direction);
|
ELOG("Invalid focus direction (%s)\n", direction);
|
||||||
cmd_output->json_output = sstrdup("{\"success\": false}");
|
ysuccess(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd_output->needs_tree_render = true;
|
cmd_output->needs_tree_render = true;
|
||||||
// XXX: default reply for now, make this a better reply
|
// XXX: default reply for now, make this a better reply
|
||||||
cmd_output->json_output = sstrdup("{\"success\": true}");
|
ysuccess(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1136,7 +1166,7 @@ void cmd_focus_window_mode(I3_CMD, char *window_mode) {
|
||||||
focused->type != CT_WORKSPACE &&
|
focused->type != CT_WORKSPACE &&
|
||||||
focused->fullscreen_mode != CF_NONE) {
|
focused->fullscreen_mode != CF_NONE) {
|
||||||
LOG("Cannot change focus while in fullscreen mode.\n");
|
LOG("Cannot change focus while in fullscreen mode.\n");
|
||||||
cmd_output->json_output = sstrdup("{\"success\": false}");
|
ysuccess(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1163,7 +1193,7 @@ void cmd_focus_window_mode(I3_CMD, char *window_mode) {
|
||||||
|
|
||||||
cmd_output->needs_tree_render = true;
|
cmd_output->needs_tree_render = true;
|
||||||
// XXX: default reply for now, make this a better reply
|
// XXX: default reply for now, make this a better reply
|
||||||
cmd_output->json_output = sstrdup("{\"success\": true}");
|
ysuccess(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1175,7 +1205,7 @@ void cmd_focus_level(I3_CMD, char *level) {
|
||||||
focused->type != CT_WORKSPACE &&
|
focused->type != CT_WORKSPACE &&
|
||||||
focused->fullscreen_mode != CF_NONE) {
|
focused->fullscreen_mode != CF_NONE) {
|
||||||
LOG("Cannot change focus while in fullscreen mode.\n");
|
LOG("Cannot change focus while in fullscreen mode.\n");
|
||||||
cmd_output->json_output = sstrdup("{\"success\": false}");
|
ysuccess(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1187,7 +1217,7 @@ void cmd_focus_level(I3_CMD, char *level) {
|
||||||
|
|
||||||
cmd_output->needs_tree_render = true;
|
cmd_output->needs_tree_render = true;
|
||||||
// XXX: default reply for now, make this a better reply
|
// XXX: default reply for now, make this a better reply
|
||||||
cmd_output->json_output = sstrdup("{\"success\": true}");
|
ysuccess(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1200,7 +1230,7 @@ void cmd_focus(I3_CMD) {
|
||||||
focused->type != CT_WORKSPACE &&
|
focused->type != CT_WORKSPACE &&
|
||||||
focused->fullscreen_mode != CF_NONE) {
|
focused->fullscreen_mode != CF_NONE) {
|
||||||
LOG("Cannot change focus while in fullscreen mode.\n");
|
LOG("Cannot change focus while in fullscreen mode.\n");
|
||||||
cmd_output->json_output = sstrdup("{\"success\": false}");
|
ysuccess(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1210,9 +1240,13 @@ void cmd_focus(I3_CMD) {
|
||||||
ELOG("You have to specify which window/container should be focused.\n");
|
ELOG("You have to specify which window/container should be focused.\n");
|
||||||
ELOG("Example: [class=\"urxvt\" title=\"irssi\"] focus\n");
|
ELOG("Example: [class=\"urxvt\" title=\"irssi\"] focus\n");
|
||||||
|
|
||||||
sasprintf(&(cmd_output->json_output),
|
y(map_open);
|
||||||
"{\"success\":false, \"error\":\"You have to "
|
ystr("success");
|
||||||
"specify which window/container should be focused\"}");
|
y(bool, false);
|
||||||
|
ystr("error");
|
||||||
|
ystr("You have to specify which window/container should be focused");
|
||||||
|
y(map_close);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1253,7 +1287,7 @@ void cmd_focus(I3_CMD) {
|
||||||
|
|
||||||
cmd_output->needs_tree_render = true;
|
cmd_output->needs_tree_render = true;
|
||||||
// XXX: default reply for now, make this a better reply
|
// XXX: default reply for now, make this a better reply
|
||||||
cmd_output->json_output = sstrdup("{\"success\": true}");
|
ysuccess(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1275,7 +1309,7 @@ void cmd_fullscreen(I3_CMD, char *fullscreen_mode) {
|
||||||
|
|
||||||
cmd_output->needs_tree_render = true;
|
cmd_output->needs_tree_render = true;
|
||||||
// XXX: default reply for now, make this a better reply
|
// XXX: default reply for now, make this a better reply
|
||||||
cmd_output->json_output = sstrdup("{\"success\": true}");
|
ysuccess(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1310,7 +1344,7 @@ void cmd_move_direction(I3_CMD, char *direction, char *move_px) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// XXX: default reply for now, make this a better reply
|
// XXX: default reply for now, make this a better reply
|
||||||
cmd_output->json_output = sstrdup("{\"success\": true}");
|
ysuccess(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1338,7 +1372,7 @@ void cmd_layout(I3_CMD, char *layout_str) {
|
||||||
|
|
||||||
cmd_output->needs_tree_render = true;
|
cmd_output->needs_tree_render = true;
|
||||||
// XXX: default reply for now, make this a better reply
|
// XXX: default reply for now, make this a better reply
|
||||||
cmd_output->json_output = sstrdup("{\"success\": true}");
|
ysuccess(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1365,7 +1399,7 @@ void cmd_reload(I3_CMD) {
|
||||||
ipc_send_event("workspace", I3_IPC_EVENT_WORKSPACE, "{\"change\":\"reload\"}");
|
ipc_send_event("workspace", I3_IPC_EVENT_WORKSPACE, "{\"change\":\"reload\"}");
|
||||||
|
|
||||||
// XXX: default reply for now, make this a better reply
|
// XXX: default reply for now, make this a better reply
|
||||||
cmd_output->json_output = sstrdup("{\"success\": true}");
|
ysuccess(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1377,7 +1411,7 @@ void cmd_restart(I3_CMD) {
|
||||||
i3_restart(false);
|
i3_restart(false);
|
||||||
|
|
||||||
// XXX: default reply for now, make this a better reply
|
// XXX: default reply for now, make this a better reply
|
||||||
cmd_output->json_output = sstrdup("{\"success\": true}");
|
ysuccess(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1388,8 +1422,13 @@ void cmd_open(I3_CMD) {
|
||||||
LOG("opening new container\n");
|
LOG("opening new container\n");
|
||||||
Con *con = tree_open_con(NULL, NULL);
|
Con *con = tree_open_con(NULL, NULL);
|
||||||
con_focus(con);
|
con_focus(con);
|
||||||
sasprintf(&(cmd_output->json_output),
|
|
||||||
"{\"success\":true, \"id\":%ld}", (long int)con);
|
y(map_open);
|
||||||
|
ystr("success");
|
||||||
|
y(bool, true);
|
||||||
|
ystr("id");
|
||||||
|
y(integer, (long int)con);
|
||||||
|
y(map_close);
|
||||||
|
|
||||||
cmd_output->needs_tree_render = true;
|
cmd_output->needs_tree_render = true;
|
||||||
}
|
}
|
||||||
|
@ -1417,7 +1456,7 @@ void cmd_focus_output(I3_CMD, char *name) {
|
||||||
|
|
||||||
if (!output) {
|
if (!output) {
|
||||||
LOG("No such output found.\n");
|
LOG("No such output found.\n");
|
||||||
cmd_output->json_output = sstrdup("{\"success\": false}");
|
ysuccess(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1425,7 +1464,7 @@ void cmd_focus_output(I3_CMD, char *name) {
|
||||||
Con *ws = NULL;
|
Con *ws = NULL;
|
||||||
GREP_FIRST(ws, output_get_content(output->con), workspace_is_visible(child));
|
GREP_FIRST(ws, output_get_content(output->con), workspace_is_visible(child));
|
||||||
if (!ws) {
|
if (!ws) {
|
||||||
cmd_output->json_output = sstrdup("{\"success\": false}");
|
ysuccess(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1433,7 +1472,7 @@ void cmd_focus_output(I3_CMD, char *name) {
|
||||||
|
|
||||||
cmd_output->needs_tree_render = true;
|
cmd_output->needs_tree_render = true;
|
||||||
// XXX: default reply for now, make this a better reply
|
// XXX: default reply for now, make this a better reply
|
||||||
cmd_output->json_output = sstrdup("{\"success\": true}");
|
ysuccess(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1447,9 +1486,12 @@ void cmd_move_window_to_position(I3_CMD, char *method, char *cx, char *cy) {
|
||||||
|
|
||||||
if (!con_is_floating(focused)) {
|
if (!con_is_floating(focused)) {
|
||||||
ELOG("Cannot change position. The window/container is not floating\n");
|
ELOG("Cannot change position. The window/container is not floating\n");
|
||||||
sasprintf(&(cmd_output->json_output),
|
y(map_open);
|
||||||
"{\"success\":false, \"error\":\"Cannot change position. "
|
ystr("success");
|
||||||
"The window/container is not floating.\"}");
|
y(bool, false);
|
||||||
|
ystr("error");
|
||||||
|
ystr("Cannot change position. The window/container is not floating.");
|
||||||
|
y(map_close);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1473,7 +1515,7 @@ void cmd_move_window_to_position(I3_CMD, char *method, char *cx, char *cy) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// XXX: default reply for now, make this a better reply
|
// XXX: default reply for now, make this a better reply
|
||||||
cmd_output->json_output = sstrdup("{\"success\": true}");
|
ysuccess(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1484,9 +1526,12 @@ void cmd_move_window_to_center(I3_CMD, char *method) {
|
||||||
|
|
||||||
if (!con_is_floating(focused)) {
|
if (!con_is_floating(focused)) {
|
||||||
ELOG("Cannot change position. The window/container is not floating\n");
|
ELOG("Cannot change position. The window/container is not floating\n");
|
||||||
sasprintf(&(cmd_output->json_output),
|
y(map_open);
|
||||||
"{\"success\":false, \"error\":\"Cannot change position. "
|
ystr("success");
|
||||||
"The window/container is not floating.\"}");
|
y(bool, false);
|
||||||
|
ystr("error");
|
||||||
|
ystr("Cannot change position. The window/container is not floating.");
|
||||||
|
y(map_close);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp(method, "absolute") == 0) {
|
if (strcmp(method, "absolute") == 0) {
|
||||||
|
@ -1512,7 +1557,7 @@ void cmd_move_window_to_center(I3_CMD, char *method) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// XXX: default reply for now, make this a better reply
|
// XXX: default reply for now, make this a better reply
|
||||||
cmd_output->json_output = sstrdup("{\"success\": true}");
|
ysuccess(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1532,7 +1577,7 @@ void cmd_move_scratchpad(I3_CMD) {
|
||||||
|
|
||||||
cmd_output->needs_tree_render = true;
|
cmd_output->needs_tree_render = true;
|
||||||
// XXX: default reply for now, make this a better reply
|
// XXX: default reply for now, make this a better reply
|
||||||
cmd_output->json_output = sstrdup("{\"success\": true}");
|
ysuccess(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1554,7 +1599,7 @@ void cmd_scratchpad_show(I3_CMD) {
|
||||||
|
|
||||||
cmd_output->needs_tree_render = true;
|
cmd_output->needs_tree_render = true;
|
||||||
// XXX: default reply for now, make this a better reply
|
// XXX: default reply for now, make this a better reply
|
||||||
cmd_output->json_output = sstrdup("{\"success\": true}");
|
ysuccess(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1572,8 +1617,13 @@ void cmd_rename_workspace(I3_CMD, char *old_name, char *new_name) {
|
||||||
if (!workspace) {
|
if (!workspace) {
|
||||||
// TODO: we should include the old workspace name here and use yajl for
|
// TODO: we should include the old workspace name here and use yajl for
|
||||||
// generating the reply.
|
// generating the reply.
|
||||||
cmd_output->json_output = sstrdup("{\"success\": false, "
|
y(map_open);
|
||||||
"\"error\":\"Old workspace not found\"}");
|
ystr("success");
|
||||||
|
y(bool, false);
|
||||||
|
ystr("error");
|
||||||
|
// TODO: better error message
|
||||||
|
ystr("Old workspace not found");
|
||||||
|
y(map_close);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1585,8 +1635,13 @@ void cmd_rename_workspace(I3_CMD, char *old_name, char *new_name) {
|
||||||
if (check_dest != NULL) {
|
if (check_dest != NULL) {
|
||||||
// TODO: we should include the new workspace name here and use yajl for
|
// TODO: we should include the new workspace name here and use yajl for
|
||||||
// generating the reply.
|
// generating the reply.
|
||||||
cmd_output->json_output = sstrdup("{\"success\": false, "
|
y(map_open);
|
||||||
"\"error\":\"New workspace already exists\"}");
|
ystr("success");
|
||||||
|
y(bool, false);
|
||||||
|
ystr("error");
|
||||||
|
// TODO: better error message
|
||||||
|
ystr("New workspace already exists");
|
||||||
|
y(map_close);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1612,7 +1667,7 @@ void cmd_rename_workspace(I3_CMD, char *old_name, char *new_name) {
|
||||||
con_focus(previously_focused);
|
con_focus(previously_focused);
|
||||||
|
|
||||||
cmd_output->needs_tree_render = true;
|
cmd_output->needs_tree_render = true;
|
||||||
cmd_output->json_output = sstrdup("{\"success\": true}");
|
ysuccess(true);
|
||||||
|
|
||||||
ipc_send_event("workspace", I3_IPC_EVENT_WORKSPACE, "{\"change\":\"rename\"}");
|
ipc_send_event("workspace", I3_IPC_EVENT_WORKSPACE, "{\"change\":\"rename\"}");
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,10 @@
|
||||||
|
|
||||||
#include "all.h"
|
#include "all.h"
|
||||||
|
|
||||||
|
// Macros to make the YAJL API a bit easier to use.
|
||||||
|
#define y(x, ...) yajl_gen_ ## x (command_output.json_gen, ##__VA_ARGS__)
|
||||||
|
#define ystr(str) yajl_gen_string(command_output.json_gen, (unsigned char*)str, strlen(str))
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* The data structures used for parsing. Essentially the current state and a
|
* The data structures used for parsing. Essentially the current state and a
|
||||||
* list of tokens for that state.
|
* list of tokens for that state.
|
||||||
|
@ -185,20 +189,9 @@ static void next_state(const cmdp_token *token) {
|
||||||
if (token->next_state == __CALL) {
|
if (token->next_state == __CALL) {
|
||||||
DLOG("should call stuff, yay. call_id = %d\n",
|
DLOG("should call stuff, yay. call_id = %d\n",
|
||||||
token->extra.call_identifier);
|
token->extra.call_identifier);
|
||||||
subcommand_output.json_output = NULL;
|
subcommand_output.json_gen = command_output.json_gen;
|
||||||
subcommand_output.needs_tree_render = false;
|
subcommand_output.needs_tree_render = false;
|
||||||
GENERATED_call(token->extra.call_identifier, &subcommand_output);
|
GENERATED_call(token->extra.call_identifier, &subcommand_output);
|
||||||
if (subcommand_output.json_output) {
|
|
||||||
DLOG("Subcommand JSON output: %s\n", subcommand_output.json_output);
|
|
||||||
char *buffer;
|
|
||||||
/* In the beginning, the contents of json_output are "[\0". */
|
|
||||||
if (command_output.json_output[1] == '\0')
|
|
||||||
sasprintf(&buffer, "%s%s", command_output.json_output, subcommand_output.json_output);
|
|
||||||
else sasprintf(&buffer, "%s, %s", command_output.json_output, subcommand_output.json_output);
|
|
||||||
free(command_output.json_output);
|
|
||||||
command_output.json_output = buffer;
|
|
||||||
DLOG("merged command JSON output: %s\n", command_output.json_output);
|
|
||||||
}
|
|
||||||
/* If any subcommand requires a tree_render(), we need to make the
|
/* If any subcommand requires a tree_render(), we need to make the
|
||||||
* whole parser result request a tree_render(). */
|
* whole parser result request a tree_render(). */
|
||||||
if (subcommand_output.needs_tree_render)
|
if (subcommand_output.needs_tree_render)
|
||||||
|
@ -217,7 +210,15 @@ static void next_state(const cmdp_token *token) {
|
||||||
struct CommandResult *parse_command(const char *input) {
|
struct CommandResult *parse_command(const char *input) {
|
||||||
DLOG("new parser handling: %s\n", input);
|
DLOG("new parser handling: %s\n", input);
|
||||||
state = INITIAL;
|
state = INITIAL;
|
||||||
command_output.json_output = sstrdup("[");
|
|
||||||
|
/* A YAJL JSON generator used for formatting replies. */
|
||||||
|
#if YAJL_MAJOR >= 2
|
||||||
|
command_output.json_gen = yajl_gen_alloc(NULL);
|
||||||
|
#else
|
||||||
|
command_output.json_gen = yajl_gen_alloc(NULL, NULL);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
y(array_open);
|
||||||
command_output.needs_tree_render = false;
|
command_output.needs_tree_render = false;
|
||||||
|
|
||||||
const char *walk = input;
|
const char *walk = input;
|
||||||
|
@ -392,6 +393,18 @@ struct CommandResult *parse_command(const char *input) {
|
||||||
printf("Your command: %s\n", input);
|
printf("Your command: %s\n", input);
|
||||||
printf(" %s\n", position);
|
printf(" %s\n", position);
|
||||||
|
|
||||||
|
/* Format this error message as a JSON reply. */
|
||||||
|
y(map_open);
|
||||||
|
ystr("success");
|
||||||
|
y(bool, false);
|
||||||
|
ystr("error");
|
||||||
|
ystr(errormessage);
|
||||||
|
ystr("input");
|
||||||
|
ystr(input);
|
||||||
|
ystr("errorposition");
|
||||||
|
ystr(position);
|
||||||
|
y(map_close);
|
||||||
|
|
||||||
free(position);
|
free(position);
|
||||||
free(errormessage);
|
free(errormessage);
|
||||||
clear_stack();
|
clear_stack();
|
||||||
|
@ -399,11 +412,8 @@ struct CommandResult *parse_command(const char *input) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
char *buffer;
|
y(array_close);
|
||||||
sasprintf(&buffer, "%s]", command_output.json_output);
|
|
||||||
free(command_output.json_output);
|
|
||||||
command_output.json_output = buffer;
|
|
||||||
DLOG("command_output.json_output = %s\n", command_output.json_output);
|
|
||||||
DLOG("command_output.needs_tree_render = %d\n", command_output.needs_tree_render);
|
DLOG("command_output.needs_tree_render = %d\n", command_output.needs_tree_render);
|
||||||
return &command_output;
|
return &command_output;
|
||||||
}
|
}
|
||||||
|
|
|
@ -124,7 +124,7 @@ static void handle_key_press(xcb_key_press_event_t *event) {
|
||||||
if (command_output->needs_tree_render)
|
if (command_output->needs_tree_render)
|
||||||
tree_render();
|
tree_render();
|
||||||
|
|
||||||
free(command_output->json_output);
|
yajl_gen_free(command_output->json_gen);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
16
src/ipc.c
16
src/ipc.c
|
@ -125,12 +125,18 @@ IPC_HANDLER(command) {
|
||||||
if (command_output->needs_tree_render)
|
if (command_output->needs_tree_render)
|
||||||
tree_render();
|
tree_render();
|
||||||
|
|
||||||
/* If no reply was provided, we just use the default success message */
|
const unsigned char *reply;
|
||||||
ipc_send_message(fd, strlen(command_output->json_output),
|
#if YAJL_MAJOR >= 2
|
||||||
I3_IPC_REPLY_TYPE_COMMAND,
|
size_t length;
|
||||||
(const uint8_t*)command_output->json_output);
|
#else
|
||||||
|
unsigned int length;
|
||||||
|
#endif
|
||||||
|
yajl_gen_get_buf(command_output->json_gen, &reply, &length);
|
||||||
|
|
||||||
free(command_output->json_output);
|
ipc_send_message(fd, length, I3_IPC_REPLY_TYPE_COMMAND,
|
||||||
|
(const uint8_t*)reply);
|
||||||
|
|
||||||
|
yajl_gen_free(command_output->json_gen);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dump_rect(yajl_gen gen, const char *name, Rect r) {
|
static void dump_rect(yajl_gen gen, const char *name, Rect r) {
|
||||||
|
|
|
@ -63,4 +63,12 @@ cmd 'move gibberish' for (0 .. 10);
|
||||||
|
|
||||||
does_i3_live;
|
does_i3_live;
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
# regression test: an invalid command should come back with an error.
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
my $reply = cmd 'bullshit-command-which-we-never-implement meh';
|
||||||
|
is(scalar @$reply, 1, 'got one command reply');
|
||||||
|
ok(!$reply->[0]->{success}, 'reply has success == false');
|
||||||
|
|
||||||
done_testing;
|
done_testing;
|
||||||
|
|
Loading…
Reference in New Issue