Add abstraction for running a binding
Add run_binding function to bindings.h. > Runs the given binding and handles parse errors. Returns a > CommandResult for running the binding's command. Caller should render > tree if needs_tree_render is true. Free with command_result_free().
This commit is contained in:
parent
7b06e20105
commit
7482a0f642
|
@ -9,6 +9,8 @@
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
extern pid_t command_error_nagbar_pid;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The name of the default mode.
|
* The name of the default mode.
|
||||||
*
|
*
|
||||||
|
@ -57,3 +59,11 @@ void switch_mode(const char *new_mode);
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void check_for_duplicate_bindings(struct context *context);
|
void check_for_duplicate_bindings(struct context *context);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runs the given binding and handles parse errors. Returns a CommandResult for
|
||||||
|
* running the binding's command. Caller should render tree if
|
||||||
|
* needs_tree_render is true. Free with command_result_free().
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
CommandResult *run_binding(Binding *bind);
|
||||||
|
|
|
@ -9,8 +9,6 @@
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
extern pid_t command_error_nagbar_pid;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* There was a key press. We compare this key code with our bindings table and pass
|
* There was a key press. We compare this key code with our bindings table and pass
|
||||||
* the bound action to parse_command().
|
* the bound action to parse_command().
|
||||||
|
|
|
@ -8,6 +8,8 @@
|
||||||
*/
|
*/
|
||||||
#include "all.h"
|
#include "all.h"
|
||||||
|
|
||||||
|
pid_t command_error_nagbar_pid = -1;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The name of the default mode.
|
* The name of the default mode.
|
||||||
*
|
*
|
||||||
|
@ -379,3 +381,45 @@ void check_for_duplicate_bindings(struct context *context) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Runs the given binding and handles parse errors. Returns a CommandResult for
|
||||||
|
* running the binding's command. Caller should render tree if
|
||||||
|
* needs_tree_render is true. Free with command_result_free().
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
CommandResult *run_binding(Binding *bind) {
|
||||||
|
/* We need to copy the command since “reload” may be part of the command,
|
||||||
|
* and then the memory that bind->command points to may not contain the
|
||||||
|
* same data anymore. */
|
||||||
|
char *command_copy = sstrdup(bind->command);
|
||||||
|
CommandResult *result = parse_command(command_copy, NULL);
|
||||||
|
free(command_copy);
|
||||||
|
|
||||||
|
if (result->needs_tree_render)
|
||||||
|
tree_render();
|
||||||
|
|
||||||
|
if (result->parse_error) {
|
||||||
|
char *pageraction;
|
||||||
|
sasprintf(&pageraction, "i3-sensible-pager \"%s\"\n", errorfilename);
|
||||||
|
char *argv[] = {
|
||||||
|
NULL, /* will be replaced by the executable path */
|
||||||
|
"-f",
|
||||||
|
config.font.pattern,
|
||||||
|
"-t",
|
||||||
|
"error",
|
||||||
|
"-m",
|
||||||
|
"The configured command for this shortcut could not be run successfully.",
|
||||||
|
"-b",
|
||||||
|
"show errors",
|
||||||
|
pageraction,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
start_nagbar(&command_error_nagbar_pid, argv);
|
||||||
|
free(pageraction);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO: emit event for running a binding */
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
|
@ -9,50 +9,8 @@
|
||||||
* key_press.c: key press handler
|
* key_press.c: key press handler
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <sys/wait.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include "all.h"
|
#include "all.h"
|
||||||
|
|
||||||
static int current_nesting_level;
|
|
||||||
static bool parse_error_key;
|
|
||||||
static bool command_failed;
|
|
||||||
|
|
||||||
pid_t command_error_nagbar_pid = -1;
|
|
||||||
|
|
||||||
static int json_boolean(void *ctx, int boolval) {
|
|
||||||
DLOG("Got bool: %d, parse_error_key %d, nesting_level %d\n", boolval, parse_error_key, current_nesting_level);
|
|
||||||
|
|
||||||
if (parse_error_key && current_nesting_level == 1 && boolval)
|
|
||||||
command_failed = true;
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int json_map_key(void *ctx, const unsigned char *stringval, size_t stringlen) {
|
|
||||||
parse_error_key = (stringlen >= strlen("parse_error") &&
|
|
||||||
strncmp((const char*)stringval, "parse_error", strlen("parse_error")) == 0);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int json_start_map(void *ctx) {
|
|
||||||
current_nesting_level++;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int json_end_map(void *ctx) {
|
|
||||||
current_nesting_level--;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static yajl_callbacks command_error_callbacks = {
|
|
||||||
.yajl_boolean = json_boolean,
|
|
||||||
.yajl_start_map = json_start_map,
|
|
||||||
.yajl_map_key = json_map_key,
|
|
||||||
.yajl_end_map = json_end_map,
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* There was a KeyPress or KeyRelease (both events have the same fields). We
|
* There was a KeyPress or KeyRelease (both events have the same fields). We
|
||||||
* compare this key code with our bindings table and pass the bound action to
|
* compare this key code with our bindings table and pass the bound action to
|
||||||
|
@ -72,53 +30,10 @@ void handle_key_press(xcb_key_press_event_t *event) {
|
||||||
if (bind == NULL)
|
if (bind == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
yajl_gen gen = yajl_gen_alloc(NULL);
|
CommandResult *result = run_binding(bind);
|
||||||
|
|
||||||
char *command_copy = sstrdup(bind->command);
|
|
||||||
CommandResult *result = parse_command(command_copy, gen);
|
|
||||||
free(command_copy);
|
|
||||||
|
|
||||||
if (result->needs_tree_render)
|
if (result->needs_tree_render)
|
||||||
tree_render();
|
tree_render();
|
||||||
|
|
||||||
command_result_free(result);
|
command_result_free(result);
|
||||||
|
|
||||||
/* We parse the JSON reply to figure out whether there was an error
|
|
||||||
* ("success" being false in on of the returned dictionaries). */
|
|
||||||
const unsigned char *reply;
|
|
||||||
size_t length;
|
|
||||||
yajl_handle handle = yajl_alloc(&command_error_callbacks, NULL, NULL);
|
|
||||||
yajl_gen_get_buf(gen, &reply, &length);
|
|
||||||
|
|
||||||
current_nesting_level = 0;
|
|
||||||
parse_error_key = false;
|
|
||||||
command_failed = false;
|
|
||||||
yajl_status state = yajl_parse(handle, reply, length);
|
|
||||||
if (state != yajl_status_ok) {
|
|
||||||
ELOG("Could not parse my own reply. That's weird. reply is %.*s\n", (int)length, reply);
|
|
||||||
} else {
|
|
||||||
if (command_failed) {
|
|
||||||
char *pageraction;
|
|
||||||
sasprintf(&pageraction, "i3-sensible-pager \"%s\"\n", errorfilename);
|
|
||||||
char *argv[] = {
|
|
||||||
NULL, /* will be replaced by the executable path */
|
|
||||||
"-f",
|
|
||||||
config.font.pattern,
|
|
||||||
"-t",
|
|
||||||
"error",
|
|
||||||
"-m",
|
|
||||||
"The configured command for this shortcut could not be run successfully.",
|
|
||||||
"-b",
|
|
||||||
"show errors",
|
|
||||||
pageraction,
|
|
||||||
NULL
|
|
||||||
};
|
|
||||||
start_nagbar(&command_error_nagbar_pid, argv);
|
|
||||||
free(pageraction);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
yajl_free(handle);
|
|
||||||
|
|
||||||
yajl_gen_free(gen);
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue