3 * vim:ts=4:sw=4:expandtab
5 * i3 - an improved dynamic tiling window manager
6 * © 2009-2012 Michael Stapelberg and contributors (see also: LICENSE)
8 * cmdparse.y: the parser for commands you send to i3 (or bind on keys)
11 #include <sys/types.h>
19 typedef struct yy_buffer_state *YY_BUFFER_STATE;
20 extern int cmdyylex(struct context *context);
21 extern int cmdyyparse(void);
22 extern int cmdyylex_destroy(void);
24 YY_BUFFER_STATE cmdyy_scan_string(const char *);
26 static struct context *context;
27 static Match current_match;
29 /* Holds the JSON which will be returned via IPC or NULL for the default return
31 static char *json_output;
33 /* We don’t need yydebug for now, as we got decent error messages using
34 * yyerror(). Should you ever want to extend the parser, it might be handy
35 * to just comment it in again, so it stays here. */
38 void cmdyyerror(const char *error_message) {
40 ELOG("CMD: %s\n", error_message);
41 ELOG("CMD: in command:\n");
42 ELOG("CMD: %s\n", context->line_copy);
44 for (int c = 1; c <= context->last_column; c++)
45 if (c >= context->first_column)
50 context->compact_error = sstrdup(error_message);
57 char *parse_cmd(const char *new) {
59 LOG("COMMAND: *%s*\n", new);
60 cmdyy_scan_string(new);
62 cmd_criteria_init(¤t_match);
63 context = scalloc(sizeof(struct context));
64 context->filename = "cmd";
65 if (cmdyyparse() != 0) {
66 fprintf(stderr, "Could not parse command\n");
67 sasprintf(&json_output, "{\"success\":false, \"error\":\"%s at position %d\"}",
68 context->compact_error, context->first_column);
69 FREE(context->line_copy);
70 FREE(context->compact_error);
74 printf("done, json output = %s\n", json_output);
77 FREE(context->line_copy);
78 FREE(context->compact_error);
86 %lex-param { struct context *context }
94 %token TOK_EXEC "exec"
95 %token TOK_EXIT "exit"
96 %token TOK_RELOAD "reload"
97 %token TOK_RESTART "restart"
98 %token TOK_KILL "kill"
99 %token TOK_WINDOW "window"
100 %token TOK_CONTAINER "container"
101 %token TOK_CLIENT "client"
102 %token TOK_FULLSCREEN "fullscreen"
103 %token TOK_GLOBAL "global"
104 %token TOK_LAYOUT "layout"
105 %token TOK_DEFAULT "default"
106 %token TOK_STACKED "stacked"
107 %token TOK_TABBED "tabbed"
108 %token TOK_BORDER "border"
109 %token TOK_NORMAL "normal"
110 %token TOK_NONE "none"
111 %token TOK_1PIXEL "1pixel"
112 %token TOK_MODE "mode"
113 %token TOK_TILING "tiling"
114 %token TOK_FLOATING "floating"
115 %token TOK_MODE_TOGGLE "mode_toggle"
116 %token TOK_ENABLE "enable"
117 %token TOK_DISABLE "disable"
118 %token TOK_WORKSPACE "workspace"
119 %token TOK_OUTPUT "output"
120 %token TOK_TOGGLE "toggle"
121 %token TOK_FOCUS "focus"
122 %token TOK_MOVE "move"
123 %token TOK_OPEN "open"
124 %token TOK_NEXT "next"
125 %token TOK_PREV "prev"
126 %token TOK_NEXT_ON_OUTPUT "next_on_output"
127 %token TOK_PREV_ON_OUTPUT "prev_on_output"
128 %token TOK_SCRATCHPAD "scratchpad"
129 %token TOK_SHOW "show"
130 %token TOK_SPLIT "split"
131 %token TOK_HORIZONTAL "horizontal"
132 %token TOK_VERTICAL "vertical"
134 %token TOK_DOWN "down"
135 %token TOK_LEFT "left"
136 %token TOK_RIGHT "right"
137 %token TOK_PARENT "parent"
138 %token TOK_CHILD "child"
139 %token TOK_APPEND_LAYOUT "append_layout"
140 %token TOK_MARK "mark"
141 %token TOK_RESIZE "resize"
142 %token TOK_GROW "grow"
143 %token TOK_SHRINK "shrink"
148 %token TOK_BACK_AND_FORTH "back_and_forth"
149 %token TOK_NO_STARTUP_ID "--no-startup-id"
152 %token TOK_CLASS "class"
153 %token TOK_INSTANCE "instance"
154 %token TOK_WINDOW_ROLE "window_role"
156 %token TOK_CON_ID "con_id"
157 %token TOK_TITLE "title"
159 %token <string> STR "<string>"
160 %token <number> NUMBER "<number>"
162 %type <number> direction
163 %type <number> split_direction
164 %type <number> fullscreen_mode
166 %type <number> window_mode
167 %type <number> boolean
168 %type <number> border_style
169 %type <number> layout_mode
170 %type <number> resize_px
171 %type <number> resize_way
172 %type <number> resize_tiling
173 %type <number> optional_kill_mode
174 %type <number> optional_no_startup_id
182 cmd_criteria_init(¤t_match);
191 | matchstart criteria matchend
201 json_output = cmd_criteria_match_windows(¤t_match);
213 cmd_criteria_add(¤t_match, "class", $3);
216 | TOK_INSTANCE '=' STR
218 cmd_criteria_add(¤t_match, "instance", $3);
221 | TOK_WINDOW_ROLE '=' STR
223 cmd_criteria_add(¤t_match, "window_role", $3);
228 cmd_criteria_add(¤t_match, "con_id", $3);
233 cmd_criteria_add(¤t_match, "id", $3);
238 cmd_criteria_add(¤t_match, "con_mark", $3);
243 cmd_criteria_add(¤t_match, "title", $3);
250 | operations ',' operation
277 TOK_EXEC optional_no_startup_id STR
279 json_output = cmd_exec(¤t_match, ($2 ? "nosn" : NULL), $3);
284 optional_no_startup_id:
285 /* empty */ { $$ = false; }
286 | TOK_NO_STARTUP_ID { $$ = true; }
292 json_output = cmd_exit(¤t_match);
299 json_output = cmd_reload(¤t_match);
306 json_output = cmd_restart(¤t_match);
313 json_output = cmd_focus(¤t_match);
315 | TOK_FOCUS direction
317 json_output = cmd_focus_direction(¤t_match,
318 ($2 == TOK_LEFT ? "left" :
319 ($2 == TOK_RIGHT ? "right" :
320 ($2 == TOK_UP ? "up" :
323 | TOK_FOCUS TOK_OUTPUT STR
325 json_output = cmd_focus_output(¤t_match, $3);
328 | TOK_FOCUS window_mode
331 json_output = cmd_focus_window_mode(¤t_match,
332 ($2 == TOK_TILING ? "tiling" :
333 ($2 == TOK_FLOATING ? "floating" :
338 json_output = cmd_focus_level(¤t_match, ($2 == TOK_PARENT ? "parent" : "child"));
343 TOK_TILING { $$ = TOK_TILING; }
344 | TOK_FLOATING { $$ = TOK_FLOATING; }
345 | TOK_MODE_TOGGLE { $$ = TOK_MODE_TOGGLE; }
349 TOK_PARENT { $$ = TOK_PARENT; }
350 | TOK_CHILD { $$ = TOK_CHILD; }
354 TOK_KILL optional_kill_mode
356 json_output = cmd_kill(¤t_match, ($2 == KILL_WINDOW ? "window" : "client"));
361 /* empty */ { $$ = KILL_WINDOW; }
362 | TOK_WINDOW { $$ = KILL_WINDOW; }
363 | TOK_CLIENT { $$ = KILL_CLIENT; }
367 TOK_WORKSPACE TOK_NEXT
369 json_output = cmd_workspace(¤t_match, "next");
371 | TOK_WORKSPACE TOK_PREV
373 json_output = cmd_workspace(¤t_match, "prev");
375 | TOK_WORKSPACE TOK_NEXT_ON_OUTPUT
377 json_output = cmd_workspace(¤t_match, "next_on_output");
379 | TOK_WORKSPACE TOK_PREV_ON_OUTPUT
381 json_output = cmd_workspace(¤t_match, "prev_on_output");
383 | TOK_WORKSPACE TOK_BACK_AND_FORTH
385 json_output = cmd_workspace_back_and_forth(¤t_match);
389 json_output = cmd_workspace_name(¤t_match, $2);
397 json_output = cmd_open(¤t_match);
402 TOK_FULLSCREEN fullscreen_mode
404 json_output = cmd_fullscreen(¤t_match, ($2 == CF_OUTPUT ? "output" : "global"));
409 /* empty */ { $$ = CF_OUTPUT; }
410 | TOK_GLOBAL { $$ = CF_GLOBAL; }
414 TOK_SPLIT split_direction
416 char buf[2] = {'\0', '\0'};
418 json_output = cmd_split(¤t_match, buf);
423 TOK_HORIZONTAL { $$ = 'h'; }
425 | TOK_VERTICAL { $$ = 'v'; }
432 json_output = cmd_floating(¤t_match,
433 ($2 == TOK_ENABLE ? "enable" :
434 ($2 == TOK_DISABLE ? "disable" :
440 TOK_ENABLE { $$ = TOK_ENABLE; }
441 | TOK_DISABLE { $$ = TOK_DISABLE; }
442 | TOK_TOGGLE { $$ = TOK_TOGGLE; }
446 TOK_BORDER border_style
448 json_output = cmd_border(¤t_match,
449 ($2 == BS_NORMAL ? "normal" :
450 ($2 == BS_NONE ? "none" :
451 ($2 == BS_1PIXEL ? "1pixel" :
457 TOK_NORMAL { $$ = BS_NORMAL; }
458 | TOK_NONE { $$ = BS_NONE; }
459 | TOK_1PIXEL { $$ = BS_1PIXEL; }
460 | TOK_TOGGLE { $$ = TOK_TOGGLE; }
464 TOK_MOVE direction resize_px
467 snprintf(buffer, sizeof(buffer), "%d", $3);
468 json_output = cmd_move_direction(¤t_match,
469 ($2 == TOK_LEFT ? "left" :
470 ($2 == TOK_RIGHT ? "right" :
471 ($2 == TOK_UP ? "up" :
475 | TOK_MOVE TOK_WORKSPACE STR
477 json_output = cmd_move_con_to_workspace_name(¤t_match, $3);
479 | TOK_MOVE TOK_WORKSPACE TOK_NEXT
481 json_output = cmd_move_con_to_workspace(¤t_match, "next");
483 | TOK_MOVE TOK_WORKSPACE TOK_PREV
485 json_output = cmd_move_con_to_workspace(¤t_match, "prev");
487 | TOK_MOVE TOK_WORKSPACE TOK_NEXT_ON_OUTPUT
489 json_output = cmd_move_con_to_workspace(¤t_match, "next_on_output");
491 | TOK_MOVE TOK_WORKSPACE TOK_PREV_ON_OUTPUT
493 json_output = cmd_move_con_to_workspace(¤t_match, "prev_on_output");
495 | TOK_MOVE TOK_OUTPUT STR
497 json_output = cmd_move_con_to_output(¤t_match, $3);
500 | TOK_MOVE TOK_SCRATCHPAD
502 json_output = cmd_move_scratchpad(¤t_match);
504 | TOK_MOVE TOK_WORKSPACE TOK_TO TOK_OUTPUT STR
506 json_output = cmd_move_workspace_to_output(¤t_match, $5);
512 TOK_APPEND_LAYOUT STR
514 json_output = cmd_append_layout(¤t_match, $2);
520 TOK_LAYOUT layout_mode
522 json_output = cmd_layout(¤t_match,
523 ($2 == L_DEFAULT ? "default" :
524 ($2 == L_STACKED ? "stacked" :
530 TOK_DEFAULT { $$ = L_DEFAULT; }
531 | TOK_STACKED { $$ = L_STACKED; }
532 | TOK_TABBED { $$ = L_TABBED; }
538 json_output = cmd_mark(¤t_match, $2);
546 json_output = cmd_nop(¤t_match, $2);
552 TOK_SCRATCHPAD TOK_SHOW
554 json_output = cmd_scratchpad_show(¤t_match);
560 TOK_RESIZE resize_way direction resize_px resize_tiling
562 char buffer1[128], buffer2[128];
563 snprintf(buffer1, sizeof(buffer1), "%d", $4);
564 snprintf(buffer2, sizeof(buffer2), "%d", $5);
565 json_output = cmd_resize(¤t_match,
566 ($2 == TOK_SHRINK ? "shrink" : "grow"),
567 ($3 == TOK_LEFT ? "left" :
568 ($3 == TOK_RIGHT ? "right" :
569 ($3 == TOK_DOWN ? "down" :
592 | TOK_OR NUMBER TOK_PPT
599 TOK_GROW { $$ = TOK_GROW; }
600 | TOK_SHRINK { $$ = TOK_SHRINK; }
604 TOK_UP { $$ = TOK_UP; }
605 | TOK_DOWN { $$ = TOK_DOWN; }
606 | TOK_LEFT { $$ = TOK_LEFT; }
607 | TOK_RIGHT { $$ = TOK_RIGHT; }
613 json_output = cmd_mode(¤t_match, $2);