summaryrefslogtreecommitdiffstats
path: root/sway/commands.c
diff options
context:
space:
mode:
Diffstat (limited to 'sway/commands.c')
-rw-r--r--sway/commands.c197
1 files changed, 80 insertions, 117 deletions
diff --git a/sway/commands.c b/sway/commands.c
index 5c782e99..72d53ff0 100644
--- a/sway/commands.c
+++ b/sway/commands.c
@@ -96,7 +96,7 @@ static int bindsym_sort(const void *_lbind, const void *_rbind) {
96 return (rbind->keys->length + rmod) - (lbind->keys->length + lmod); 96 return (rbind->keys->length + rmod) - (lbind->keys->length + lmod);
97} 97}
98 98
99static bool cmd_bindsym(struct sway_config *config, int argc, char **argv) { 99static bool cmd_bindsym(int argc, char **argv) {
100 if (!checkarg(argc, "bindsym", EXPECTED_MORE_THAN, 1)) { 100 if (!checkarg(argc, "bindsym", EXPECTED_MORE_THAN, 1)) {
101 return false; 101 return false;
102 }; 102 };
@@ -146,7 +146,7 @@ static bool cmd_bindsym(struct sway_config *config, int argc, char **argv) {
146 return true; 146 return true;
147} 147}
148 148
149static bool cmd_exec_always(struct sway_config *config, int argc, char **argv) { 149static bool cmd_exec_always(int argc, char **argv) {
150 if (!checkarg(argc, "exec_always", EXPECTED_MORE_THAN, 0)) { 150 if (!checkarg(argc, "exec_always", EXPECTED_MORE_THAN, 0)) {
151 return false; 151 return false;
152 } 152 }
@@ -171,14 +171,14 @@ static bool cmd_exec_always(struct sway_config *config, int argc, char **argv) {
171 return true; 171 return true;
172} 172}
173 173
174static bool cmd_exec(struct sway_config *config, int argc, char **argv) { 174static bool cmd_exec(int argc, char **argv) {
175 if (config->reloading) { 175 if (config->reloading) {
176 char *args = join_args(argv, argc); 176 char *args = join_args(argv, argc);
177 sway_log(L_DEBUG, "Ignoring exec %s due to reload", args); 177 sway_log(L_DEBUG, "Ignoring exec %s due to reload", args);
178 free(args); 178 free(args);
179 return true; 179 return true;
180 } 180 }
181 return cmd_exec_always(config, argc, argv); 181 return cmd_exec_always(argc, argv);
182} 182}
183 183
184static void kill_views(swayc_t *container, void *data) { 184static void kill_views(swayc_t *container, void *data) {
@@ -187,7 +187,7 @@ static void kill_views(swayc_t *container, void *data) {
187 } 187 }
188} 188}
189 189
190static bool cmd_exit(struct sway_config *config, int argc, char **argv) { 190static bool cmd_exit(int argc, char **argv) {
191 if (!checkarg(argc, "exit", EXPECTED_EQUAL_TO, 0)) { 191 if (!checkarg(argc, "exit", EXPECTED_EQUAL_TO, 0)) {
192 return false; 192 return false;
193 } 193 }
@@ -197,7 +197,7 @@ static bool cmd_exit(struct sway_config *config, int argc, char **argv) {
197 return true; 197 return true;
198} 198}
199 199
200static bool cmd_floating(struct sway_config *config, int argc, char **argv) { 200static bool cmd_floating(int argc, char **argv) {
201 if (!checkarg(argc, "floating", EXPECTED_EQUAL_TO, 1)) { 201 if (!checkarg(argc, "floating", EXPECTED_EQUAL_TO, 1)) {
202 return false; 202 return false;
203 } 203 }
@@ -258,7 +258,7 @@ static bool cmd_floating(struct sway_config *config, int argc, char **argv) {
258 return true; 258 return true;
259} 259}
260 260
261static bool cmd_floating_mod(struct sway_config *config, int argc, char **argv) { 261static bool cmd_floating_mod(int argc, char **argv) {
262 if (!checkarg(argc, "floating_modifier", EXPECTED_EQUAL_TO, 1)) { 262 if (!checkarg(argc, "floating_modifier", EXPECTED_EQUAL_TO, 1)) {
263 return false; 263 return false;
264 } 264 }
@@ -282,7 +282,7 @@ static bool cmd_floating_mod(struct sway_config *config, int argc, char **argv)
282 return true; 282 return true;
283} 283}
284 284
285static bool cmd_focus(struct sway_config *config, int argc, char **argv) { 285static bool cmd_focus(int argc, char **argv) {
286 static int floating_toggled_index = 0; 286 static int floating_toggled_index = 0;
287 static int tiled_toggled_index = 0; 287 static int tiled_toggled_index = 0;
288 if (!checkarg(argc, "focus", EXPECTED_EQUAL_TO, 1)) { 288 if (!checkarg(argc, "focus", EXPECTED_EQUAL_TO, 1)) {
@@ -340,7 +340,7 @@ static bool cmd_focus(struct sway_config *config, int argc, char **argv) {
340 return true; 340 return true;
341} 341}
342 342
343static bool cmd_focus_follows_mouse(struct sway_config *config, int argc, char **argv) { 343static bool cmd_focus_follows_mouse(int argc, char **argv) {
344 if (!checkarg(argc, "focus_follows_mouse", EXPECTED_EQUAL_TO, 1)) { 344 if (!checkarg(argc, "focus_follows_mouse", EXPECTED_EQUAL_TO, 1)) {
345 return false; 345 return false;
346 } 346 }
@@ -365,7 +365,40 @@ static void hide_view_in_scratchpad(swayc_t *sp_view) {
365 set_focused_container(container_under_pointer()); 365 set_focused_container(container_under_pointer());
366} 366}
367 367
368static bool cmd_move(struct sway_config *config, int argc, char **argv) { 368static bool cmd_mode(int argc, char **argv) {
369 if (!checkarg(argc, "move", EXPECTED_AT_LEAST, 1)) {
370 return false;
371 }
372 const char *mode_name = argv[0];
373 struct sway_mode *mode = NULL;
374 // Find mode
375 int i, len = config->modes->length;
376 for (i = 0; i < len; ++i) {
377 struct sway_mode *find = config->modes->items[i];
378 if (strcasecmp(find->name, mode_name)==0) {
379 mode = find;
380 break;
381 }
382 }
383 // Create mode if it doesnt exist
384 if (!mode && argc >= 2 && strncmp(argv[1],"{",1) == 0) {
385 mode = malloc(sizeof*mode);
386 mode->name = malloc(strlen(mode_name) + 1);
387 mode->bindings = create_list();
388 strcpy(mode->name, mode_name);
389 list_add(config->modes, mode);
390 }
391 if (!mode) {
392 sway_log(L_ERROR, "Invalide mode `%s'", mode_name);
393 return false;
394 }
395 sway_log(L_DEBUG, "Switching to mode `%s'",mode->name);
396 // Set current mode
397 config->current_mode = mode;
398 return true;
399}
400
401static bool cmd_move(int argc, char **argv) {
369 if (!checkarg(argc, "move", EXPECTED_AT_LEAST, 1)) { 402 if (!checkarg(argc, "move", EXPECTED_AT_LEAST, 1)) {
370 return false; 403 return false;
371 } 404 }
@@ -435,7 +468,7 @@ static bool cmd_move(struct sway_config *config, int argc, char **argv) {
435 return true; 468 return true;
436} 469}
437 470
438static bool cmd_orientation(struct sway_config *config, int argc, char **argv) { 471static bool cmd_orientation(int argc, char **argv) {
439 if (strcasecmp(argv[0], "horizontal") == 0) { 472 if (strcasecmp(argv[0], "horizontal") == 0) {
440 config->default_orientation = L_HORIZ; 473 config->default_orientation = L_HORIZ;
441 } else if (strcasecmp(argv[0], "vertical") == 0) { 474 } else if (strcasecmp(argv[0], "vertical") == 0) {
@@ -448,7 +481,7 @@ static bool cmd_orientation(struct sway_config *config, int argc, char **argv) {
448 return true; 481 return true;
449} 482}
450 483
451static bool cmd_output(struct sway_config *config, int argc, char **argv) { 484static bool cmd_output(int argc, char **argv) {
452 if (!checkarg(argc, "output", EXPECTED_AT_LEAST, 1)) { 485 if (!checkarg(argc, "output", EXPECTED_AT_LEAST, 1)) {
453 return false; 486 return false;
454 } 487 }
@@ -513,7 +546,7 @@ static bool cmd_output(struct sway_config *config, int argc, char **argv) {
513 return true; 546 return true;
514} 547}
515 548
516static bool cmd_gaps(struct sway_config *config, int argc, char **argv) { 549static bool cmd_gaps(int argc, char **argv) {
517 if (!checkarg(argc, "gaps", EXPECTED_AT_LEAST, 1)) { 550 if (!checkarg(argc, "gaps", EXPECTED_AT_LEAST, 1)) {
518 return false; 551 return false;
519 } 552 }
@@ -655,13 +688,13 @@ static bool cmd_gaps(struct sway_config *config, int argc, char **argv) {
655 return true; 688 return true;
656} 689}
657 690
658static bool cmd_kill(struct sway_config *config, int argc, char **argv) { 691static bool cmd_kill(int argc, char **argv) {
659 swayc_t *view = get_focused_container(&root_container); 692 swayc_t *view = get_focused_container(&root_container);
660 wlc_view_close(view->handle); 693 wlc_view_close(view->handle);
661 return true; 694 return true;
662} 695}
663 696
664static bool cmd_layout(struct sway_config *config, int argc, char **argv) { 697static bool cmd_layout(int argc, char **argv) {
665 if (!checkarg(argc, "layout", EXPECTED_MORE_THAN, 0)) { 698 if (!checkarg(argc, "layout", EXPECTED_MORE_THAN, 0)) {
666 return false; 699 return false;
667 } 700 }
@@ -686,7 +719,7 @@ static bool cmd_layout(struct sway_config *config, int argc, char **argv) {
686 return true; 719 return true;
687} 720}
688 721
689static bool cmd_reload(struct sway_config *config, int argc, char **argv) { 722static bool cmd_reload(int argc, char **argv) {
690 if (!checkarg(argc, "reload", EXPECTED_EQUAL_TO, 0)) { 723 if (!checkarg(argc, "reload", EXPECTED_EQUAL_TO, 0)) {
691 return false; 724 return false;
692 } 725 }
@@ -697,7 +730,7 @@ static bool cmd_reload(struct sway_config *config, int argc, char **argv) {
697 return true; 730 return true;
698} 731}
699 732
700static bool cmd_resize(struct sway_config *config, int argc, char **argv) { 733static bool cmd_resize(int argc, char **argv) {
701 if (!checkarg(argc, "resize", EXPECTED_AT_LEAST, 3)) { 734 if (!checkarg(argc, "resize", EXPECTED_AT_LEAST, 3)) {
702 return false; 735 return false;
703 } 736 }
@@ -769,7 +802,7 @@ void remove_view_from_scratchpad(swayc_t *view) {
769 } 802 }
770} 803}
771 804
772static bool cmd_scratchpad(struct sway_config *config, int argc, char **argv) { 805static bool cmd_scratchpad(int argc, char **argv) {
773 if (!checkarg(argc, "scratchpad", EXPECTED_EQUAL_TO, 1)) { 806 if (!checkarg(argc, "scratchpad", EXPECTED_EQUAL_TO, 1)) {
774 return false; 807 return false;
775 } 808 }
@@ -796,7 +829,7 @@ static bool cmd_scratchpad(struct sway_config *config, int argc, char **argv) {
796 } 829 }
797} 830}
798 831
799static bool cmd_set(struct sway_config *config, int argc, char **argv) { 832static bool cmd_set(int argc, char **argv) {
800 if (!checkarg(argc, "set", EXPECTED_EQUAL_TO, 2)) { 833 if (!checkarg(argc, "set", EXPECTED_EQUAL_TO, 2)) {
801 return false; 834 return false;
802 } 835 }
@@ -809,7 +842,7 @@ static bool cmd_set(struct sway_config *config, int argc, char **argv) {
809 return true; 842 return true;
810} 843}
811 844
812static bool _do_split(struct sway_config *config, int argc, char **argv, int layout) { 845static bool _do_split(int argc, char **argv, int layout) {
813 char *name = layout == L_VERT ? "splitv" : 846 char *name = layout == L_VERT ? "splitv" :
814 layout == L_HORIZ ? "splith" : "split"; 847 layout == L_HORIZ ? "splith" : "split";
815 if (!checkarg(argc, name, EXPECTED_EQUAL_TO, 0)) { 848 if (!checkarg(argc, name, EXPECTED_EQUAL_TO, 0)) {
@@ -840,15 +873,15 @@ static bool _do_split(struct sway_config *config, int argc, char **argv, int lay
840 return true; 873 return true;
841} 874}
842 875
843static bool cmd_split(struct sway_config *config, int argc, char **argv) { 876static bool cmd_split(int argc, char **argv) {
844 if (!checkarg(argc, "split", EXPECTED_EQUAL_TO, 1)) { 877 if (!checkarg(argc, "split", EXPECTED_EQUAL_TO, 1)) {
845 return false; 878 return false;
846 } 879 }
847 880
848 if (strcasecmp(argv[0], "v") == 0 || strcasecmp(argv[0], "vertical") == 0) { 881 if (strcasecmp(argv[0], "v") == 0 || strcasecmp(argv[0], "vertical") == 0) {
849 _do_split(config, argc - 1, argv + 1, L_VERT); 882 _do_split(argc - 1, argv + 1, L_VERT);
850 } else if (strcasecmp(argv[0], "h") == 0 || strcasecmp(argv[0], "horizontal") == 0) { 883 } else if (strcasecmp(argv[0], "h") == 0 || strcasecmp(argv[0], "horizontal") == 0) {
851 _do_split(config, argc - 1, argv + 1, L_HORIZ); 884 _do_split(argc - 1, argv + 1, L_HORIZ);
852 } else { 885 } else {
853 sway_log(L_ERROR, "Invalid split command (expected either horiziontal or vertical)."); 886 sway_log(L_ERROR, "Invalid split command (expected either horiziontal or vertical).");
854 return false; 887 return false;
@@ -857,15 +890,15 @@ static bool cmd_split(struct sway_config *config, int argc, char **argv) {
857 return true; 890 return true;
858} 891}
859 892
860static bool cmd_splitv(struct sway_config *config, int argc, char **argv) { 893static bool cmd_splitv(int argc, char **argv) {
861 return _do_split(config, argc, argv, L_VERT); 894 return _do_split(argc, argv, L_VERT);
862} 895}
863 896
864static bool cmd_splith(struct sway_config *config, int argc, char **argv) { 897static bool cmd_splith(int argc, char **argv) {
865 return _do_split(config, argc, argv, L_HORIZ); 898 return _do_split(argc, argv, L_HORIZ);
866} 899}
867 900
868static bool cmd_log_colors(struct sway_config *config, int argc, char **argv) { 901static bool cmd_log_colors(int argc, char **argv) {
869 if (!checkarg(argc, "log_colors", EXPECTED_EQUAL_TO, 1)) { 902 if (!checkarg(argc, "log_colors", EXPECTED_EQUAL_TO, 1)) {
870 return false; 903 return false;
871 } 904 }
@@ -878,7 +911,7 @@ static bool cmd_log_colors(struct sway_config *config, int argc, char **argv) {
878 return true; 911 return true;
879} 912}
880 913
881static bool cmd_fullscreen(struct sway_config *config, int argc, char **argv) { 914static bool cmd_fullscreen(int argc, char **argv) {
882 if (!checkarg(argc, "fullscreen", EXPECTED_AT_LEAST, 0)) { 915 if (!checkarg(argc, "fullscreen", EXPECTED_AT_LEAST, 0)) {
883 return false; 916 return false;
884 } 917 }
@@ -897,7 +930,7 @@ static bool cmd_fullscreen(struct sway_config *config, int argc, char **argv) {
897 return true; 930 return true;
898} 931}
899 932
900static bool cmd_workspace(struct sway_config *config, int argc, char **argv) { 933static bool cmd_workspace(int argc, char **argv) {
901 if (!checkarg(argc, "workspace", EXPECTED_AT_LEAST, 1)) { 934 if (!checkarg(argc, "workspace", EXPECTED_AT_LEAST, 1)) {
902 return false; 935 return false;
903 } 936 }
@@ -953,7 +986,7 @@ static bool cmd_workspace(struct sway_config *config, int argc, char **argv) {
953 return true; 986 return true;
954} 987}
955 988
956static bool cmd_ws_auto_back_and_forth(struct sway_config *config, int argc, char **argv) { 989static bool cmd_ws_auto_back_and_forth(int argc, char **argv) {
957 if (!checkarg(argc, "workspace_auto_back_and_forth", EXPECTED_EQUAL_TO, 1)) { 990 if (!checkarg(argc, "workspace_auto_back_and_forth", EXPECTED_EQUAL_TO, 1)) {
958 return false; 991 return false;
959 } 992 }
@@ -979,6 +1012,7 @@ static struct cmd_handler handlers[] = {
979 { "kill", cmd_kill, CMD_KEYBIND }, 1012 { "kill", cmd_kill, CMD_KEYBIND },
980 { "layout", cmd_layout, CMD_KEYBIND }, 1013 { "layout", cmd_layout, CMD_KEYBIND },
981 { "log_colors", cmd_log_colors, CMD_ANYTIME }, 1014 { "log_colors", cmd_log_colors, CMD_ANYTIME },
1015 { "mode", cmd_mode, CMD_ANYTIME },
982 { "move", cmd_move, CMD_KEYBIND }, 1016 { "move", cmd_move, CMD_KEYBIND },
983 { "output", cmd_output, CMD_ANYTIME }, 1017 { "output", cmd_output, CMD_ANYTIME },
984 { "reload", cmd_reload, CMD_KEYBIND }, 1018 { "reload", cmd_reload, CMD_KEYBIND },
@@ -992,58 +1026,6 @@ static struct cmd_handler handlers[] = {
992 { "workspace_auto_back_and_forth", cmd_ws_auto_back_and_forth, CMD_ANYTIME }, 1026 { "workspace_auto_back_and_forth", cmd_ws_auto_back_and_forth, CMD_ANYTIME },
993}; 1027};
994 1028
995static char **split_directive(char *line, int *argc) {
996 const char *delimiters = " ";
997 *argc = 0;
998 while (isspace(*line) && *line) ++line;
999
1000 int capacity = 10;
1001 char **parts = malloc(sizeof(char *) * capacity);
1002
1003 if (!*line) return parts;
1004
1005 int in_string = 0, in_character = 0;
1006 int i, j, _;
1007 for (i = 0, j = 0; line[i]; ++i) {
1008 if (line[i] == '\\') {
1009 ++i;
1010 } else if (line[i] == '"' && !in_character) {
1011 in_string = !in_string;
1012 } else if (line[i] == '\'' && !in_string) {
1013 in_character = !in_character;
1014 } else if (!in_character && !in_string) {
1015 if (strchr(delimiters, line[i]) != NULL) {
1016 char *item = malloc(i - j + 1);
1017 strncpy(item, line + j, i - j);
1018 item[i - j] = '\0';
1019 item = strip_whitespace(item, &_);
1020 if (item[0] == '\0') {
1021 free(item);
1022 } else {
1023 if (*argc == capacity) {
1024 capacity *= 2;
1025 parts = realloc(parts, sizeof(char *) * capacity);
1026 }
1027 parts[*argc] = item;
1028 j = i + 1;
1029 ++*argc;
1030 }
1031 }
1032 }
1033 }
1034 char *item = malloc(i - j + 1);
1035 strncpy(item, line + j, i - j);
1036 item[i - j] = '\0';
1037 item = strip_whitespace(item, &_);
1038 if (*argc == capacity) {
1039 capacity++;
1040 parts = realloc(parts, sizeof(char *) * capacity);
1041 }
1042 parts[*argc] = item;
1043 ++*argc;
1044 return parts;
1045}
1046
1047static int handler_compare(const void *_a, const void *_b) { 1029static int handler_compare(const void *_a, const void *_b) {
1048 const struct cmd_handler *a = _a; 1030 const struct cmd_handler *a = _a;
1049 const struct cmd_handler *b = _b; 1031 const struct cmd_handler *b = _b;
@@ -1058,44 +1040,25 @@ struct cmd_handler *find_handler(char *line) {
1058 return res; 1040 return res;
1059} 1041}
1060 1042
1061bool handle_command(struct sway_config *config, char *exec) { 1043bool handle_command(char *exec) {
1062 sway_log(L_INFO, "Handling command '%s'", exec); 1044 sway_log(L_INFO, "Handling command '%s'", exec);
1063 char *ptr, *cmd; 1045 int argc;
1064 bool exec_success; 1046 char **argv = split_args(exec, &argc);
1065 1047 if (argc == 0) {
1066 if ((ptr = strchr(exec, ' ')) == NULL) { 1048 return false;
1067 cmd = exec; 1049 }
1068 } else { 1050 struct cmd_handler *handler = find_handler(argv[0]);
1069 int index = ptr - exec; 1051 bool exec_success = false;
1070 cmd = malloc(index + 1); 1052 if (handler) {
1071 strncpy(cmd, exec, index);
1072 cmd[index] = '\0';
1073 }
1074 struct cmd_handler *handler = find_handler(cmd);
1075 if (handler == NULL) {
1076 sway_log(L_ERROR, "Unknown command '%s'", cmd);
1077 exec_success = false; // TODO: return error, probably
1078 } else {
1079 int argc;
1080 char **argv = split_directive(exec + strlen(handler->command), &argc);
1081 int i; 1053 int i;
1082 1054 for (i = 1; i < argc; ++i) {
1083 // Perform var subs on all parts of the command 1055 argv[i] = do_var_replacement(argv[i]);
1084 for (i = 0; i < argc; ++i) {
1085 argv[i] = do_var_replacement(config, argv[i]);
1086 }
1087
1088 exec_success = handler->handle(config, argc, argv);
1089 for (i = 0; i < argc; ++i) {
1090 free(argv[i]);
1091 }
1092 free(argv);
1093 if (!exec_success) {
1094 sway_log(L_ERROR, "Command failed: %s", cmd);
1095 } 1056 }
1057 exec_success = handler->handle(argc - 1, argv + 1);
1096 } 1058 }
1097 if (ptr) { 1059 if (exec_success == false) {
1098 free(cmd); 1060 sway_log(L_ERROR, "Command failed: %s", argv[0]);
1099 } 1061 }
1062 free_argv(argc, argv);
1100 return exec_success; 1063 return exec_success;
1101} 1064}