i3 - improved tiling WM


Add abstraction for running a binding

Patch status: merged

Patch by Tony Crisci

Long description:

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().

To apply this patch, use:
curl http://cr.i3wm.org/patch/562/raw.patch | git am

b/include/bindings.h

21
@@ -9,6 +9,8 @@
22
  */
23
 #pragma once
24
 
25
+extern pid_t command_error_nagbar_pid;
26
+
27
 /**
28
  * The name of the default mode.
29
  *
30
@@ -57,3 +59,11 @@ void switch_mode(const char *new_mode);
31
  *
32
  */
33
 void check_for_duplicate_bindings(struct context *context);
34
+
35
+/**
36
+ * Runs the given binding and handles parse errors. Returns a CommandResult for
37
+ * running the binding's command. Caller should render tree if
38
+ * needs_tree_render is true. Free with command_result_free().
39
+ *
40
+ */
41
+CommandResult *run_binding(Binding *bind);

b/include/key_press.h

46
@@ -9,8 +9,6 @@
47
  */
48
 #pragma once
49
 
50
-extern pid_t command_error_nagbar_pid;
51
-
52
 /**
53
  * There was a key press. We compare this key code with our bindings table and pass
54
  * the bound action to parse_command().

b/src/bindings.c

59
@@ -8,6 +8,8 @@
60
  */
61
 #include "all.h"
62
 
63
+pid_t command_error_nagbar_pid = -1;
64
+
65
 /*
66
  * The name of the default mode.
67
  *
68
@@ -379,3 +381,42 @@ void check_for_duplicate_bindings(struct context *context) {
69
         }
70
     }
71
 }
72
+
73
+/*
74
+ * Runs the given binding and handles parse errors. Returns a CommandResult for
75
+ * running the binding's command. Caller should render tree if
76
+ * needs_tree_render is true. Free with command_result_free().
77
+ *
78
+ */
79
+CommandResult *run_binding(Binding *bind) {
80
+    char *command_copy = sstrdup(bind->command);
81
+    CommandResult *result = parse_command(command_copy, NULL);
82
+    free(command_copy);
83
+
84
+    if (result->needs_tree_render)
85
+        tree_render();
86
+
87
+    if (result->parse_error) {
88
+        char *pageraction;
89
+        sasprintf(&pageraction, "i3-sensible-pager \"%s\"\n", errorfilename);
90
+        char *argv[] = {
91
+            NULL, /* will be replaced by the executable path */
92
+            "-f",
93
+            config.font.pattern,
94
+            "-t",
95
+            "error",
96
+            "-m",
97
+            "The configured command for this shortcut could not be run successfully.",
98
+            "-b",
99
+            "show errors",
100
+            pageraction,
101
+            NULL
102
+        };
103
+        start_nagbar(&command_error_nagbar_pid, argv);
104
+        free(pageraction);
105
+    }
106
+
107
+    /* TODO: emit event for running a binding */
108
+
109
+    return result;
110
+}

b/src/key_press.c

115
@@ -9,50 +9,8 @@
116
  * key_press.c: key press handler
117
  *
118
  */
119
-#include <sys/types.h>
120
-#include <sys/stat.h>
121
-#include <sys/wait.h>
122
-#include <fcntl.h>
123
 #include "all.h"
124
 
125
-static int current_nesting_level;
126
-static bool parse_error_key;
127
-static bool command_failed;
128
-
129
-pid_t command_error_nagbar_pid = -1;
130
-
131
-static int json_boolean(void *ctx, int boolval) {
132
-    DLOG("Got bool: %d, parse_error_key %d, nesting_level %d\n", boolval, parse_error_key, current_nesting_level);
133
-
134
-    if (parse_error_key && current_nesting_level == 1 && boolval)
135
-        command_failed = true;
136
-
137
-    return 1;
138
-}
139
-
140
-static int json_map_key(void *ctx, const unsigned char *stringval, size_t stringlen) {
141
-    parse_error_key = (stringlen >= strlen("parse_error") &&
142
-                       strncmp((const char*)stringval, "parse_error", strlen("parse_error")) == 0);
143
-    return 1;
144
-}
145
-
146
-static int json_start_map(void *ctx) {
147
-    current_nesting_level++;
148
-    return 1;
149
-}
150
-
151
-static int json_end_map(void *ctx) {
152
-    current_nesting_level--;
153
-    return 1;
154
-}
155
-
156
-static yajl_callbacks command_error_callbacks = {
157
-    .yajl_boolean = json_boolean,
158
-    .yajl_start_map = json_start_map,
159
-    .yajl_map_key = json_map_key,
160
-    .yajl_end_map = json_end_map,
161
-};
162
-
163
 /*
164
  * There was a KeyPress or KeyRelease (both events have the same fields). We
165
  * compare this key code with our bindings table and pass the bound action to
166
@@ -72,53 +30,10 @@ void handle_key_press(xcb_key_press_event_t *event) {
167
     if (bind == NULL)
168
         return;
169
 
170
-    yajl_gen gen = yajl_gen_alloc(NULL);
171
-
172
-    char *command_copy = sstrdup(bind->command);
173
-    CommandResult *result = parse_command(command_copy, gen);
174
-    free(command_copy);
175
+    CommandResult *result = run_binding(bind);
176
 
177
     if (result->needs_tree_render)
178
         tree_render();
179
 
180
     command_result_free(result);
181
-
182
-    /* We parse the JSON reply to figure out whether there was an error
183
-     * ("success" being false in on of the returned dictionaries). */
184
-    const unsigned char *reply;
185
-    size_t length;
186
-    yajl_handle handle = yajl_alloc(&command_error_callbacks, NULL, NULL);
187
-    yajl_gen_get_buf(gen, &reply, &length);
188
-
189
-    current_nesting_level = 0;
190
-    parse_error_key = false;
191
-    command_failed = false;
192
-    yajl_status state = yajl_parse(handle, reply, length);
193
-    if (state != yajl_status_ok) {
194
-        ELOG("Could not parse my own reply. That's weird. reply is %.*s\n", (int)length, reply);
195
-    } else {
196
-        if (command_failed) {
197
-            char *pageraction;
198
-            sasprintf(&pageraction, "i3-sensible-pager \"%s\"\n", errorfilename);
199
-            char *argv[] = {
200
-                NULL, /* will be replaced by the executable path */
201
-                "-f",
202
-                config.font.pattern,
203
-                "-t",
204
-                "error",
205
-                "-m",
206
-                "The configured command for this shortcut could not be run successfully.",
207
-                "-b",
208
-                "show errors",
209
-                pageraction,
210
-                NULL
211
-            };
212
-            start_nagbar(&command_error_nagbar_pid, argv);
213
-            free(pageraction);
214
-        }
215
-    }
216
-
217
-    yajl_free(handle);
218
-
219
-    yajl_gen_free(gen);
220
 }