summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Drew DeVault <sir@cmpwn.com>2015-09-07 18:14:37 -0400
committerLibravatar Drew DeVault <sir@cmpwn.com>2015-09-07 18:14:37 -0400
commit7654f5e7cdbf5edff2f576a59cf04c530dd6efb5 (patch)
tree8496fd8673d31bac1802d756885a8fc64245a552
parentMerge pull request #172 from taiyu-len/master (diff)
parentstrdup + style (diff)
downloadsway-7654f5e7cdbf5edff2f576a59cf04c530dd6efb5.tar.gz
sway-7654f5e7cdbf5edff2f576a59cf04c530dd6efb5.tar.zst
sway-7654f5e7cdbf5edff2f576a59cf04c530dd6efb5.zip
Merge pull request #173 from taiyu-len/config_mode
config modes
-rw-r--r--include/commands.h4
-rw-r--r--include/config.h2
-rw-r--r--include/stringop.h12
-rw-r--r--sway/commands.c202
-rw-r--r--sway/config.c108
-rw-r--r--sway/handlers.c11
-rw-r--r--sway/ipc.c2
-rw-r--r--sway/stringop.c130
8 files changed, 250 insertions, 221 deletions
diff --git a/include/commands.h b/include/commands.h
index 808e64eb..8fb0c1d8 100644
--- a/include/commands.h
+++ b/include/commands.h
@@ -5,7 +5,7 @@
5 5
6struct cmd_handler { 6struct cmd_handler {
7 char *command; 7 char *command;
8 bool (*handle)(struct sway_config *config, int argc, char **argv); 8 bool (*handle)(int argc, char **argv);
9 enum { 9 enum {
10 CMD_COMPOSITOR_READY, 10 CMD_COMPOSITOR_READY,
11 CMD_KEYBIND, 11 CMD_KEYBIND,
@@ -14,7 +14,7 @@ struct cmd_handler {
14}; 14};
15 15
16struct cmd_handler *find_handler(char *line); 16struct cmd_handler *find_handler(char *line);
17bool handle_command(struct sway_config *config, char *command); 17bool handle_command(char *command);
18 18
19void remove_view_from_scratchpad(); 19void remove_view_from_scratchpad();
20 20
diff --git a/include/config.h b/include/config.h
index 653e790f..4070c9ef 100644
--- a/include/config.h
+++ b/include/config.h
@@ -60,7 +60,7 @@ struct sway_config {
60 60
61bool load_config(const char *file); 61bool load_config(const char *file);
62bool read_config(FILE *file, bool is_active); 62bool read_config(FILE *file, bool is_active);
63char *do_var_replacement(struct sway_config *config, char *str); 63char *do_var_replacement(char *str);
64 64
65extern struct sway_config *config; 65extern struct sway_config *config;
66 66
diff --git a/include/stringop.h b/include/stringop.h
index 7d17af95..dde50f13 100644
--- a/include/stringop.h
+++ b/include/stringop.h
@@ -2,17 +2,25 @@
2#define _SWAY_STRINGOP_H 2#define _SWAY_STRINGOP_H
3#include "list.h" 3#include "list.h"
4 4
5char *strip_whitespace(char *str, int *trimmed_start); 5// array of whitespace characters to use for delims
6extern const char *whitespace;
7
8char *strip_whitespace(char *str);
6char *strip_comments(char *str); 9char *strip_comments(char *str);
7 10
8// Must be freed with free_flat_list 11// Simply split a string with delims, free with `free_flat_list`
9list_t *split_string(const char *str, const char *delims); 12list_t *split_string(const char *str, const char *delims);
10void free_flat_list(list_t *list); 13void free_flat_list(list_t *list);
11 14
15// Splits an argument string, keeping quotes intact
16char **split_args(const char *str, int *argc);
17void free_argv(int argc, char **argv);
18
12char *code_strchr(const char *string, char delimiter); 19char *code_strchr(const char *string, char delimiter);
13char *code_strstr(const char *haystack, const char *needle); 20char *code_strstr(const char *haystack, const char *needle);
14int unescape_string(char *string); 21int unescape_string(char *string);
15char *join_args(char **argv, int argc); 22char *join_args(char **argv, int argc);
16char *join_list(list_t *list, char *separator); 23char *join_list(list_t *list, char *separator);
17 24
25char *strdup(const char *);
18#endif 26#endif
diff --git a/sway/commands.c b/sway/commands.c
index 5c782e99..e7ddfa71 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,39 @@ 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 = strdup(mode_name);
387 mode->bindings = create_list();
388 list_add(config->modes, mode);
389 }
390 if (!mode) {
391 sway_log(L_ERROR, "Invalide mode `%s'", mode_name);
392 return false;
393 }
394 sway_log(L_DEBUG, "Switching to mode `%s'",mode->name);
395 // Set current mode
396 config->current_mode = mode;
397 return true;
398}
399
400static bool cmd_move(int argc, char **argv) {
369 if (!checkarg(argc, "move", EXPECTED_AT_LEAST, 1)) { 401 if (!checkarg(argc, "move", EXPECTED_AT_LEAST, 1)) {
370 return false; 402 return false;
371 } 403 }
@@ -435,7 +467,7 @@ static bool cmd_move(struct sway_config *config, int argc, char **argv) {
435 return true; 467 return true;
436} 468}
437 469
438static bool cmd_orientation(struct sway_config *config, int argc, char **argv) { 470static bool cmd_orientation(int argc, char **argv) {
439 if (strcasecmp(argv[0], "horizontal") == 0) { 471 if (strcasecmp(argv[0], "horizontal") == 0) {
440 config->default_orientation = L_HORIZ; 472 config->default_orientation = L_HORIZ;
441 } else if (strcasecmp(argv[0], "vertical") == 0) { 473 } else if (strcasecmp(argv[0], "vertical") == 0) {
@@ -448,7 +480,7 @@ static bool cmd_orientation(struct sway_config *config, int argc, char **argv) {
448 return true; 480 return true;
449} 481}
450 482
451static bool cmd_output(struct sway_config *config, int argc, char **argv) { 483static bool cmd_output(int argc, char **argv) {
452 if (!checkarg(argc, "output", EXPECTED_AT_LEAST, 1)) { 484 if (!checkarg(argc, "output", EXPECTED_AT_LEAST, 1)) {
453 return false; 485 return false;
454 } 486 }
@@ -513,7 +545,7 @@ static bool cmd_output(struct sway_config *config, int argc, char **argv) {
513 return true; 545 return true;
514} 546}
515 547
516static bool cmd_gaps(struct sway_config *config, int argc, char **argv) { 548static bool cmd_gaps(int argc, char **argv) {
517 if (!checkarg(argc, "gaps", EXPECTED_AT_LEAST, 1)) { 549 if (!checkarg(argc, "gaps", EXPECTED_AT_LEAST, 1)) {
518 return false; 550 return false;
519 } 551 }
@@ -655,13 +687,13 @@ static bool cmd_gaps(struct sway_config *config, int argc, char **argv) {
655 return true; 687 return true;
656} 688}
657 689
658static bool cmd_kill(struct sway_config *config, int argc, char **argv) { 690static bool cmd_kill(int argc, char **argv) {
659 swayc_t *view = get_focused_container(&root_container); 691 swayc_t *view = get_focused_container(&root_container);
660 wlc_view_close(view->handle); 692 wlc_view_close(view->handle);
661 return true; 693 return true;
662} 694}
663 695
664static bool cmd_layout(struct sway_config *config, int argc, char **argv) { 696static bool cmd_layout(int argc, char **argv) {
665 if (!checkarg(argc, "layout", EXPECTED_MORE_THAN, 0)) { 697 if (!checkarg(argc, "layout", EXPECTED_MORE_THAN, 0)) {
666 return false; 698 return false;
667 } 699 }
@@ -686,7 +718,7 @@ static bool cmd_layout(struct sway_config *config, int argc, char **argv) {
686 return true; 718 return true;
687} 719}
688 720
689static bool cmd_reload(struct sway_config *config, int argc, char **argv) { 721static bool cmd_reload(int argc, char **argv) {
690 if (!checkarg(argc, "reload", EXPECTED_EQUAL_TO, 0)) { 722 if (!checkarg(argc, "reload", EXPECTED_EQUAL_TO, 0)) {
691 return false; 723 return false;
692 } 724 }
@@ -697,7 +729,7 @@ static bool cmd_reload(struct sway_config *config, int argc, char **argv) {
697 return true; 729 return true;
698} 730}
699 731
700static bool cmd_resize(struct sway_config *config, int argc, char **argv) { 732static bool cmd_resize(int argc, char **argv) {
701 if (!checkarg(argc, "resize", EXPECTED_AT_LEAST, 3)) { 733 if (!checkarg(argc, "resize", EXPECTED_AT_LEAST, 3)) {
702 return false; 734 return false;
703 } 735 }
@@ -769,7 +801,7 @@ void remove_view_from_scratchpad(swayc_t *view) {
769 } 801 }
770} 802}
771 803
772static bool cmd_scratchpad(struct sway_config *config, int argc, char **argv) { 804static bool cmd_scratchpad(int argc, char **argv) {
773 if (!checkarg(argc, "scratchpad", EXPECTED_EQUAL_TO, 1)) { 805 if (!checkarg(argc, "scratchpad", EXPECTED_EQUAL_TO, 1)) {
774 return false; 806 return false;
775 } 807 }
@@ -796,20 +828,18 @@ static bool cmd_scratchpad(struct sway_config *config, int argc, char **argv) {
796 } 828 }
797} 829}
798 830
799static bool cmd_set(struct sway_config *config, int argc, char **argv) { 831static bool cmd_set(int argc, char **argv) {
800 if (!checkarg(argc, "set", EXPECTED_EQUAL_TO, 2)) { 832 if (!checkarg(argc, "set", EXPECTED_EQUAL_TO, 2)) {
801 return false; 833 return false;
802 } 834 }
803 struct sway_variable *var = malloc(sizeof(struct sway_variable)); 835 struct sway_variable *var = malloc(sizeof(struct sway_variable));
804 var->name = malloc(strlen(argv[0]) + 1); 836 var->name = strdup(argv[0]);
805 strcpy(var->name, argv[0]); 837 var->value = strdup(argv[1]);
806 var->value = malloc(strlen(argv[1]) + 1);
807 strcpy(var->value, argv[1]);
808 list_add(config->symbols, var); 838 list_add(config->symbols, var);
809 return true; 839 return true;
810} 840}
811 841
812static bool _do_split(struct sway_config *config, int argc, char **argv, int layout) { 842static bool _do_split(int argc, char **argv, int layout) {
813 char *name = layout == L_VERT ? "splitv" : 843 char *name = layout == L_VERT ? "splitv" :
814 layout == L_HORIZ ? "splith" : "split"; 844 layout == L_HORIZ ? "splith" : "split";
815 if (!checkarg(argc, name, EXPECTED_EQUAL_TO, 0)) { 845 if (!checkarg(argc, name, EXPECTED_EQUAL_TO, 0)) {
@@ -840,15 +870,15 @@ static bool _do_split(struct sway_config *config, int argc, char **argv, int lay
840 return true; 870 return true;
841} 871}
842 872
843static bool cmd_split(struct sway_config *config, int argc, char **argv) { 873static bool cmd_split(int argc, char **argv) {
844 if (!checkarg(argc, "split", EXPECTED_EQUAL_TO, 1)) { 874 if (!checkarg(argc, "split", EXPECTED_EQUAL_TO, 1)) {
845 return false; 875 return false;
846 } 876 }
847 877
848 if (strcasecmp(argv[0], "v") == 0 || strcasecmp(argv[0], "vertical") == 0) { 878 if (strcasecmp(argv[0], "v") == 0 || strcasecmp(argv[0], "vertical") == 0) {
849 _do_split(config, argc - 1, argv + 1, L_VERT); 879 _do_split(argc - 1, argv + 1, L_VERT);
850 } else if (strcasecmp(argv[0], "h") == 0 || strcasecmp(argv[0], "horizontal") == 0) { 880 } else if (strcasecmp(argv[0], "h") == 0 || strcasecmp(argv[0], "horizontal") == 0) {
851 _do_split(config, argc - 1, argv + 1, L_HORIZ); 881 _do_split(argc - 1, argv + 1, L_HORIZ);
852 } else { 882 } else {
853 sway_log(L_ERROR, "Invalid split command (expected either horiziontal or vertical)."); 883 sway_log(L_ERROR, "Invalid split command (expected either horiziontal or vertical).");
854 return false; 884 return false;
@@ -857,15 +887,15 @@ static bool cmd_split(struct sway_config *config, int argc, char **argv) {
857 return true; 887 return true;
858} 888}
859 889
860static bool cmd_splitv(struct sway_config *config, int argc, char **argv) { 890static bool cmd_splitv(int argc, char **argv) {
861 return _do_split(config, argc, argv, L_VERT); 891 return _do_split(argc, argv, L_VERT);
862} 892}
863 893
864static bool cmd_splith(struct sway_config *config, int argc, char **argv) { 894static bool cmd_splith(int argc, char **argv) {
865 return _do_split(config, argc, argv, L_HORIZ); 895 return _do_split(argc, argv, L_HORIZ);
866} 896}
867 897
868static bool cmd_log_colors(struct sway_config *config, int argc, char **argv) { 898static bool cmd_log_colors(int argc, char **argv) {
869 if (!checkarg(argc, "log_colors", EXPECTED_EQUAL_TO, 1)) { 899 if (!checkarg(argc, "log_colors", EXPECTED_EQUAL_TO, 1)) {
870 return false; 900 return false;
871 } 901 }
@@ -878,7 +908,7 @@ static bool cmd_log_colors(struct sway_config *config, int argc, char **argv) {
878 return true; 908 return true;
879} 909}
880 910
881static bool cmd_fullscreen(struct sway_config *config, int argc, char **argv) { 911static bool cmd_fullscreen(int argc, char **argv) {
882 if (!checkarg(argc, "fullscreen", EXPECTED_AT_LEAST, 0)) { 912 if (!checkarg(argc, "fullscreen", EXPECTED_AT_LEAST, 0)) {
883 return false; 913 return false;
884 } 914 }
@@ -897,7 +927,7 @@ static bool cmd_fullscreen(struct sway_config *config, int argc, char **argv) {
897 return true; 927 return true;
898} 928}
899 929
900static bool cmd_workspace(struct sway_config *config, int argc, char **argv) { 930static bool cmd_workspace(int argc, char **argv) {
901 if (!checkarg(argc, "workspace", EXPECTED_AT_LEAST, 1)) { 931 if (!checkarg(argc, "workspace", EXPECTED_AT_LEAST, 1)) {
902 return false; 932 return false;
903 } 933 }
@@ -953,7 +983,7 @@ static bool cmd_workspace(struct sway_config *config, int argc, char **argv) {
953 return true; 983 return true;
954} 984}
955 985
956static bool cmd_ws_auto_back_and_forth(struct sway_config *config, int argc, char **argv) { 986static bool cmd_ws_auto_back_and_forth(int argc, char **argv) {
957 if (!checkarg(argc, "workspace_auto_back_and_forth", EXPECTED_EQUAL_TO, 1)) { 987 if (!checkarg(argc, "workspace_auto_back_and_forth", EXPECTED_EQUAL_TO, 1)) {
958 return false; 988 return false;
959 } 989 }
@@ -979,6 +1009,7 @@ static struct cmd_handler handlers[] = {
979 { "kill", cmd_kill, CMD_KEYBIND }, 1009 { "kill", cmd_kill, CMD_KEYBIND },
980 { "layout", cmd_layout, CMD_KEYBIND }, 1010 { "layout", cmd_layout, CMD_KEYBIND },
981 { "log_colors", cmd_log_colors, CMD_ANYTIME }, 1011 { "log_colors", cmd_log_colors, CMD_ANYTIME },
1012 { "mode", cmd_mode, CMD_ANYTIME },
982 { "move", cmd_move, CMD_KEYBIND }, 1013 { "move", cmd_move, CMD_KEYBIND },
983 { "output", cmd_output, CMD_ANYTIME }, 1014 { "output", cmd_output, CMD_ANYTIME },
984 { "reload", cmd_reload, CMD_KEYBIND }, 1015 { "reload", cmd_reload, CMD_KEYBIND },
@@ -992,58 +1023,6 @@ static struct cmd_handler handlers[] = {
992 { "workspace_auto_back_and_forth", cmd_ws_auto_back_and_forth, CMD_ANYTIME }, 1023 { "workspace_auto_back_and_forth", cmd_ws_auto_back_and_forth, CMD_ANYTIME },
993}; 1024};
994 1025
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) { 1026static int handler_compare(const void *_a, const void *_b) {
1048 const struct cmd_handler *a = _a; 1027 const struct cmd_handler *a = _a;
1049 const struct cmd_handler *b = _b; 1028 const struct cmd_handler *b = _b;
@@ -1058,44 +1037,25 @@ struct cmd_handler *find_handler(char *line) {
1058 return res; 1037 return res;
1059} 1038}
1060 1039
1061bool handle_command(struct sway_config *config, char *exec) { 1040bool handle_command(char *exec) {
1062 sway_log(L_INFO, "Handling command '%s'", exec); 1041 sway_log(L_INFO, "Handling command '%s'", exec);
1063 char *ptr, *cmd; 1042 int argc;
1064 bool exec_success; 1043 char **argv = split_args(exec, &argc);
1065 1044 if (argc == 0) {
1066 if ((ptr = strchr(exec, ' ')) == NULL) { 1045 return false;
1067 cmd = exec; 1046 }
1068 } else { 1047 struct cmd_handler *handler = find_handler(argv[0]);
1069 int index = ptr - exec; 1048 bool exec_success = false;
1070 cmd = malloc(index + 1); 1049 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; 1050 int i;
1082 1051 for (i = 1; i < argc; ++i) {
1083 // Perform var subs on all parts of the command 1052 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 } 1053 }
1054 exec_success = handler->handle(argc - 1, argv + 1);
1096 } 1055 }
1097 if (ptr) { 1056 if (exec_success == false) {
1098 free(cmd); 1057 sway_log(L_ERROR, "Command failed: %s", argv[0]);
1099 } 1058 }
1059 free_argv(argc, argv);
1100 return exec_success; 1060 return exec_success;
1101} 1061}
diff --git a/sway/config.c b/sway/config.c
index b64dd4b1..5ece2810 100644
--- a/sway/config.c
+++ b/sway/config.c
@@ -13,6 +13,7 @@
13 13
14struct sway_config *config = NULL; 14struct sway_config *config = NULL;
15 15
16
16static void free_variable(struct sway_variable *var) { 17static void free_variable(struct sway_variable *var) {
17 free(var->name); 18 free(var->name);
18 free(var->value); 19 free(var->value);
@@ -46,6 +47,33 @@ static void free_workspace_output(struct workspace_output *wo) {
46 free(wo); 47 free(wo);
47} 48}
48 49
50static void free_config(struct sway_config *config) {
51 int i;
52 for (i = 0; i < config->symbols->length; ++i) {
53 free_variable(config->symbols->items[i]);
54 }
55 list_free(config->symbols);
56
57 for (i = 0; i < config->modes->length; ++i) {
58 free_mode(config->modes->items[i]);
59 }
60 list_free(config->modes);
61
62 free_flat_list(config->cmd_queue);
63
64 for (i = 0; i < config->workspace_outputs->length; ++i) {
65 free_workspace_output(config->workspace_outputs->items[i]);
66 }
67 list_free(config->workspace_outputs);
68
69 for (i = 0; i < config->output_configs->length; ++i) {
70 free_outut_config(config->output_configs->items[i]);
71 }
72 list_free(config->output_configs);
73 free(config);
74}
75
76
49static bool file_exists(const char *path) { 77static bool file_exists(const char *path) {
50 return access(path, R_OK) != -1; 78 return access(path, R_OK) != -1;
51} 79}
@@ -59,7 +87,8 @@ static void config_defaults(struct sway_config *config) {
59 config->cmd_queue = create_list(); 87 config->cmd_queue = create_list();
60 88
61 config->current_mode = malloc(sizeof(struct sway_mode)); 89 config->current_mode = malloc(sizeof(struct sway_mode));
62 config->current_mode->name = NULL; 90 config->current_mode->name = malloc(sizeof("default"));
91 strcpy(config->current_mode->name, "default");
63 config->current_mode->bindings = create_list(); 92 config->current_mode->bindings = create_list();
64 list_add(config->modes, config->current_mode); 93 list_add(config->modes, config->current_mode);
65 94
@@ -78,32 +107,6 @@ static void config_defaults(struct sway_config *config) {
78 config->gaps_outer = 0; 107 config->gaps_outer = 0;
79} 108}
80 109
81void free_config(struct sway_config *config) {
82 int i;
83 for (i = 0; i < config->symbols->length; ++i) {
84 free_variable(config->symbols->items[i]);
85 }
86 list_free(config->symbols);
87
88 for (i = 0; i < config->modes->length; ++i) {
89 free_mode(config->modes->items[i]);
90 }
91 list_free(config->modes);
92
93 free_flat_list(config->cmd_queue);
94
95 for (i = 0; i < config->workspace_outputs->length; ++i) {
96 free_workspace_output(config->workspace_outputs->items[i]);
97 }
98 list_free(config->workspace_outputs);
99
100 for (i = 0; i < config->output_configs->length; ++i) {
101 free_outut_config(config->output_configs->items[i]);
102 }
103 list_free(config->output_configs);
104 free(config);
105}
106
107static char *get_config_path(void) { 110static char *get_config_path(void) {
108 char *config_path = NULL; 111 char *config_path = NULL;
109 char *paths[3] = {getenv("HOME"), getenv("XDG_CONFIG_HOME"), ""}; 112 char *paths[3] = {getenv("HOME"), getenv("XDG_CONFIG_HOME"), ""};
@@ -210,47 +213,48 @@ bool load_config(const char *file) {
210} 213}
211 214
212bool read_config(FILE *file, bool is_active) { 215bool read_config(FILE *file, bool is_active) {
213 struct sway_config *temp_config = malloc(sizeof(struct sway_config)); 216 struct sway_config *old_config = config;
214 config_defaults(temp_config); 217 struct sway_mode *default_mode;
218 config = malloc(sizeof(struct sway_config));
219
220 config_defaults(config);
221 default_mode = config->current_mode;
222
215 if (is_active) { 223 if (is_active) {
216 sway_log(L_DEBUG, "Performing configuration file reload"); 224 sway_log(L_DEBUG, "Performing configuration file reload");
217 temp_config->reloading = true; 225 config->reloading = true;
218 temp_config->active = true; 226 config->active = true;
219 } 227 }
220
221 bool success = true; 228 bool success = true;
222 229
223 int temp_depth = 0; // Temporary: skip all config sections with depth 230 char *line;
224
225 while (!feof(file)) { 231 while (!feof(file)) {
226 int _; 232 line = read_line(file);
227 char *line = read_line(file); 233 line = strip_whitespace(line);
228 line = strip_whitespace(line, &_);
229 line = strip_comments(line); 234 line = strip_comments(line);
230 if (!line[0]) { 235 if (line[0] == '\0') {
231 goto _continue; 236 goto _continue;
232 } 237 }
233 if (temp_depth && line[0] == '}') { 238 if (line[0] == '}') {
234 temp_depth--; 239 config->current_mode = default_mode;
235 goto _continue; 240 goto _continue;
236 } 241 }
237 242
238 // Any command which would require wlc to be initialized 243 // Any command which would require wlc to be initialized
239 // should be queued for later execution 244 // should be queued for later execution
240 list_t *args = split_string(line, " "); 245 list_t *args = split_string(line, whitespace);
241 struct cmd_handler *handler; 246 struct cmd_handler *handler;
242 if ((handler = find_handler(args->items[0]))) { 247 if ((handler = find_handler(args->items[0]))) {
243 if (handler->config_type == CMD_KEYBIND) { 248 if (handler->config_type == CMD_KEYBIND) {
244 sway_log(L_ERROR, "Invalid command during config ``%s''", line); 249 sway_log(L_ERROR, "Invalid command during config ``%s''", line);
245 } else if (handler->config_type == CMD_COMPOSITOR_READY && !is_active) { 250 } else if (handler->config_type == CMD_COMPOSITOR_READY && !is_active) {
246 sway_log(L_DEBUG, "Deferring command ``%s''", line); 251 sway_log(L_DEBUG, "Deferring command ``%s''", line);
247 char *cmd = malloc(strlen(line) + 1); 252 char *cmd = strdup(line);
248 strcpy(cmd, line); 253 list_add(config->cmd_queue, cmd);
249 list_add(temp_config->cmd_queue, cmd); 254 } else if (!handle_command(line)) {
250 } else if (!temp_depth && !handle_command(temp_config, line)) {
251 sway_log(L_DEBUG, "Config load failed for line ``%s''", line); 255 sway_log(L_DEBUG, "Config load failed for line ``%s''", line);
252 success = false; 256 success = false;
253 temp_config->failed = true; 257 config->failed = true;
254 } 258 }
255 } else { 259 } else {
256 sway_log(L_ERROR, "Invalid command ``%s''", line); 260 sway_log(L_ERROR, "Invalid command ``%s''", line);
@@ -258,25 +262,21 @@ bool read_config(FILE *file, bool is_active) {
258 free_flat_list(args); 262 free_flat_list(args);
259 263
260_continue: 264_continue:
261 if (line && line[strlen(line) - 1] == '{') {
262 temp_depth++;
263 }
264 free(line); 265 free(line);
265 } 266 }
266 267
267 if (is_active) { 268 if (is_active) {
268 temp_config->reloading = false; 269 config->reloading = false;
269 arrange_windows(&root_container, -1, -1); 270 arrange_windows(&root_container, -1, -1);
270 } 271 }
271 if (config) { 272 if (old_config) {
272 free_config(config); 273 free_config(old_config);
273 } 274 }
274 config = temp_config;
275 275
276 return success; 276 return success;
277} 277}
278 278
279char *do_var_replacement(struct sway_config *config, char *str) { 279char *do_var_replacement(char *str) {
280 // TODO: Handle escaping $ and using $ in string literals 280 // TODO: Handle escaping $ and using $ in string literals
281 int i; 281 int i;
282 for (i = 0; str[i]; ++i) { 282 for (i = 0; str[i]; ++i) {
diff --git a/sway/handlers.c b/sway/handlers.c
index 482d52c6..c0472817 100644
--- a/sway/handlers.c
+++ b/sway/handlers.c
@@ -130,13 +130,6 @@ static void handle_output_resolution_change(wlc_handle output, const struct wlc_
130 if (!c) return; 130 if (!c) return;
131 c->width = to->w; 131 c->width = to->w;
132 c->height = to->h; 132 c->height = to->h;
133 if (config->default_layout == L_NONE && config->default_orientation == L_NONE) {
134 if (c->width >= c->height) {
135 ((swayc_t*)c->children->items[0])->layout = L_HORIZ;
136 } else {
137 ((swayc_t*)c->children->items[0])->layout = L_VERT;
138 }
139 }
140 arrange_windows(&root_container, -1, -1); 133 arrange_windows(&root_container, -1, -1);
141} 134}
142 135
@@ -348,7 +341,7 @@ static bool handle_key(wlc_handle view, uint32_t time, const struct wlc_modifier
348 } 341 }
349 if (match) { 342 if (match) {
350 if (state == WLC_KEY_STATE_PRESSED) { 343 if (state == WLC_KEY_STATE_PRESSED) {
351 handle_command(config, binding->command); 344 handle_command(binding->command);
352 return EVENT_HANDLED; 345 return EVENT_HANDLED;
353 } else if (state == WLC_KEY_STATE_RELEASED) { 346 } else if (state == WLC_KEY_STATE_RELEASED) {
354 // TODO: --released 347 // TODO: --released
@@ -486,7 +479,7 @@ static void handle_wlc_ready(void) {
486 sway_log(L_DEBUG, "Compositor is ready, executing cmds in queue"); 479 sway_log(L_DEBUG, "Compositor is ready, executing cmds in queue");
487 // Execute commands until there are none left 480 // Execute commands until there are none left
488 while (config->cmd_queue->length) { 481 while (config->cmd_queue->length) {
489 handle_command(config, config->cmd_queue->items[0]); 482 handle_command(config->cmd_queue->items[0]);
490 free(config->cmd_queue->items[0]); 483 free(config->cmd_queue->items[0]);
491 list_del(config->cmd_queue, 0); 484 list_del(config->cmd_queue, 0);
492 } 485 }
diff --git a/sway/ipc.c b/sway/ipc.c
index f6217bfd..abf2ed0c 100644
--- a/sway/ipc.c
+++ b/sway/ipc.c
@@ -198,7 +198,7 @@ void ipc_client_handle_command(struct ipc_client *client) {
198 case IPC_COMMAND: 198 case IPC_COMMAND:
199 { 199 {
200 buf[client->payload_length] = '\0'; 200 buf[client->payload_length] = '\0';
201 bool success = handle_command(config, buf); 201 bool success = handle_command(buf);
202 char reply[64]; 202 char reply[64];
203 int length = snprintf(reply, sizeof(reply), "{\"success\":%s}", success ? "true" : "false"); 203 int length = snprintf(reply, sizeof(reply), "{\"success\":%s}", success ? "true" : "false");
204 ipc_send_reply(client, reply, (uint32_t) length); 204 ipc_send_reply(client, reply, (uint32_t) length);
diff --git a/sway/stringop.c b/sway/stringop.c
index c39e2c34..1ba54ec6 100644
--- a/sway/stringop.c
+++ b/sway/stringop.c
@@ -1,27 +1,23 @@
1#include "stringop.h"
2#include <stdlib.h> 1#include <stdlib.h>
3#include <stdio.h> 2#include <stdio.h>
3#include <strings.h>
4#include <ctype.h>
5#include "stringop.h"
6#include "log.h"
4#include "string.h" 7#include "string.h"
5#include "list.h" 8#include "list.h"
6#include <strings.h> 9
7#include <log.h> 10const char *whitespace = " \f\n\r\t\v";
8 11
9/* Note: This returns 8 characters for trimmed_start per tab character. */ 12/* Note: This returns 8 characters for trimmed_start per tab character. */
10char *strip_whitespace(char *_str, int *trimmed_start) { 13char *strip_whitespace(char *_str) {
11 *trimmed_start = 0;
12 if (*_str == '\0') 14 if (*_str == '\0')
13 return _str; 15 return _str;
14 char *strold = _str; 16 char *strold = _str;
15 while (*_str == ' ' || *_str == '\t') { 17 while (*_str == ' ' || *_str == '\t') {
16 if (*_str == '\t') {
17 *trimmed_start += 8;
18 } else {
19 *trimmed_start += 1;
20 }
21 _str++; 18 _str++;
22 } 19 }
23 char *str = malloc(strlen(_str) + 1); 20 char *str = strdup(_str);
24 strcpy(str, _str);
25 free(strold); 21 free(strold);
26 int i; 22 int i;
27 for (i = 0; str[i] != '\0'; ++i); 23 for (i = 0; str[i] != '\0'; ++i);
@@ -41,7 +37,7 @@ char *strip_comments(char *str) {
41 } else if (str[i] == '\'' && !in_string) { 37 } else if (str[i] == '\'' && !in_string) {
42 in_character = !in_character; 38 in_character = !in_character;
43 } else if (!in_character && !in_string) { 39 } else if (!in_character && !in_string) {
44 if (str[i] == '#' && i == 0) { 40 if (str[i] == '#') {
45 str[i] = '\0'; 41 str[i] = '\0';
46 break; 42 break;
47 } 43 }
@@ -51,26 +47,44 @@ char *strip_comments(char *str) {
51 return str; 47 return str;
52} 48}
53 49
50void strip_quotes(char *str) {
51 bool in_str = false;
52 bool in_chr = false;
53 bool escaped = false;
54 char *end = strchr(str,0);
55 while (*str) {
56 if (*str == '\'' && !in_str && !escaped) {
57 in_chr = !in_chr;
58 goto shift_over;
59 } else if (*str == '\"' && !in_chr && !escaped) {
60 in_str = !in_str;
61 goto shift_over;
62 } else if (*str == '\\') {
63 escaped = !escaped;
64 ++str;
65 continue;
66 }
67 escaped = false;
68 ++str;
69 continue;
70 shift_over:
71 memmove(str, str+1, end-- - str);
72 }
73 *end = '\0';
74}
75
54list_t *split_string(const char *str, const char *delims) { 76list_t *split_string(const char *str, const char *delims) {
55 list_t *res = create_list(); 77 list_t *res = create_list();
56 int i, j; 78 char *copy = strdup(str);
57 int len = strlen(str); 79 char *token;
58 for (i = 0, j = 0; i < len + 1; ++i) { 80
59 if (strchr(delims, str[i]) || i == len) { 81 token = strtok(copy, delims);
60 if (i - j == 0) { 82 while(token) {
61 continue; 83 token = strdup(token);
62 } 84 list_add(res, token);
63 char *left = malloc(i - j + 1); 85 token = strtok(NULL, delims);
64 memcpy(left, str + j, i - j);
65 left[i - j] = 0;
66 list_add(res, left);
67 j = i + 1;
68 while (j <= len && str[j] && strchr(delims, str[j])) {
69 j++;
70 i++;
71 }
72 }
73 } 86 }
87 free(copy);
74 return res; 88 return res;
75} 89}
76 90
@@ -82,6 +96,60 @@ void free_flat_list(list_t *list) {
82 list_free(list); 96 list_free(list);
83} 97}
84 98
99char **split_args(const char *start, int *argc) {
100 *argc = 0;
101 int alloc = 2;
102 char **parts = malloc(sizeof(char *) * alloc);
103 bool in_token = false;
104 bool in_string = false;
105 bool in_char = false;
106 bool escaped = false;
107 const char *end = start;
108 while (*start) {
109 if (!in_token) {
110 start = (end += strspn(end, whitespace));
111 in_token = true;
112 }
113 if (*end == '"' && !in_char && !escaped) {
114 in_string = !in_string;
115 } else if (*end == '\'' && !in_string && !escaped) {
116 in_char = !in_char;
117 } else if (*end == '\\') {
118 escaped = !escaped;
119 } else if (*end == '\0' || (!in_string && !in_char && !escaped
120 && strchr(whitespace, *end))) {
121 goto add_part;
122 }
123 if (*end != '\\') {
124 escaped = false;
125 }
126 ++end;
127 continue;
128 add_part:
129 if (end - start > 0) {
130 char *token = malloc(end - start + 1);
131 strncpy(token, start, end - start + 1);
132 token[end - start] = '\0';
133 strip_quotes(token);
134 unescape_string(token);
135 parts[*argc] = token;
136 if (++*argc == alloc) {
137 parts = realloc(parts, (alloc *= 2) * sizeof(char *));
138 }
139 }
140 in_token = false;
141 escaped = false;
142 }
143 return parts;
144}
145
146void free_argv(int argc, char **argv) {
147 while (--argc) {
148 free(argv[argc]);
149 }
150 free(argv);
151}
152
85char *code_strstr(const char *haystack, const char *needle) { 153char *code_strstr(const char *haystack, const char *needle) {
86 /* TODO */ 154 /* TODO */
87 return strstr(haystack, needle); 155 return strstr(haystack, needle);
@@ -177,7 +245,7 @@ int unescape_string(char *string) {
177 string[i - 1] = c; 245 string[i - 1] = c;
178 } 246 }
179 } 247 }
180 memmove(string + i, string + i + shift, len - i); 248 memmove(string + i, string + i + shift, len - i + 1);
181 } 249 }
182 } 250 }
183 return len; 251 return len;