diff options
author | taiyu <taiyu.len@gmail.com> | 2015-09-07 14:29:40 -0700 |
---|---|---|
committer | taiyu <taiyu.len@gmail.com> | 2015-09-07 14:29:40 -0700 |
commit | 71af5b7ddebe6b714f3be65bf8c810c952a7e0af (patch) | |
tree | 20eac4917bad5c08c89bffa1c33063ebda03a2f5 | |
parent | Merge pull request #172 from taiyu-len/master (diff) | |
download | sway-71af5b7ddebe6b714f3be65bf8c810c952a7e0af.tar.gz sway-71af5b7ddebe6b714f3be65bf8c810c952a7e0af.tar.zst sway-71af5b7ddebe6b714f3be65bf8c810c952a7e0af.zip |
config modes
-rw-r--r-- | include/commands.h | 4 | ||||
-rw-r--r-- | include/config.h | 2 | ||||
-rw-r--r-- | include/stringop.h | 12 | ||||
-rw-r--r-- | sway/commands.c | 197 | ||||
-rw-r--r-- | sway/config.c | 104 | ||||
-rw-r--r-- | sway/handlers.c | 11 | ||||
-rw-r--r-- | sway/ipc.c | 2 | ||||
-rw-r--r-- | sway/stringop.c | 151 |
8 files changed, 256 insertions, 227 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 | ||
6 | struct cmd_handler { | 6 | struct 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 | ||
16 | struct cmd_handler *find_handler(char *line); | 16 | struct cmd_handler *find_handler(char *line); |
17 | bool handle_command(struct sway_config *config, char *command); | 17 | bool handle_command(char *command); |
18 | 18 | ||
19 | void remove_view_from_scratchpad(); | 19 | void 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 | ||
61 | bool load_config(const char *file); | 61 | bool load_config(const char *file); |
62 | bool read_config(FILE *file, bool is_active); | 62 | bool read_config(FILE *file, bool is_active); |
63 | char *do_var_replacement(struct sway_config *config, char *str); | 63 | char *do_var_replacement(char *str); |
64 | 64 | ||
65 | extern struct sway_config *config; | 65 | extern 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 | ||
5 | char *strip_whitespace(char *str, int *trimmed_start); | 5 | // array of whitespace characters to use for delims |
6 | extern const char *whitespace; | ||
7 | |||
8 | char *strip_whitespace(char *str); | ||
6 | char *strip_comments(char *str); | 9 | char *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` |
9 | list_t *split_string(const char *str, const char *delims); | 12 | list_t *split_string(const char *str, const char *delims); |
10 | void free_flat_list(list_t *list); | 13 | void free_flat_list(list_t *list); |
11 | 14 | ||
15 | // Splits an argument string, keeping quotes intact | ||
16 | char **split_args(const char *str, int *argc); | ||
17 | void free_argv(int argc, char **argv); | ||
18 | |||
12 | char *code_strchr(const char *string, char delimiter); | 19 | char *code_strchr(const char *string, char delimiter); |
13 | char *code_strstr(const char *haystack, const char *needle); | 20 | char *code_strstr(const char *haystack, const char *needle); |
14 | int unescape_string(char *string); | 21 | int unescape_string(char *string); |
15 | char *join_args(char **argv, int argc); | 22 | char *join_args(char **argv, int argc); |
16 | char *join_list(list_t *list, char *separator); | 23 | char *join_list(list_t *list, char *separator); |
17 | 24 | ||
25 | char *strdup(const char *); | ||
18 | #endif | 26 | #endif |
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 | ||
99 | static bool cmd_bindsym(struct sway_config *config, int argc, char **argv) { | 99 | static 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 | ||
149 | static bool cmd_exec_always(struct sway_config *config, int argc, char **argv) { | 149 | static 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 | ||
174 | static bool cmd_exec(struct sway_config *config, int argc, char **argv) { | 174 | static 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 | ||
184 | static void kill_views(swayc_t *container, void *data) { | 184 | static 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 | ||
190 | static bool cmd_exit(struct sway_config *config, int argc, char **argv) { | 190 | static 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 | ||
200 | static bool cmd_floating(struct sway_config *config, int argc, char **argv) { | 200 | static 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 | ||
261 | static bool cmd_floating_mod(struct sway_config *config, int argc, char **argv) { | 261 | static 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 | ||
285 | static bool cmd_focus(struct sway_config *config, int argc, char **argv) { | 285 | static 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 | ||
343 | static bool cmd_focus_follows_mouse(struct sway_config *config, int argc, char **argv) { | 343 | static 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 | ||
368 | static bool cmd_move(struct sway_config *config, int argc, char **argv) { | 368 | static 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 | |||
401 | static 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 | ||
438 | static bool cmd_orientation(struct sway_config *config, int argc, char **argv) { | 471 | static 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 | ||
451 | static bool cmd_output(struct sway_config *config, int argc, char **argv) { | 484 | static 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 | ||
516 | static bool cmd_gaps(struct sway_config *config, int argc, char **argv) { | 549 | static 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 | ||
658 | static bool cmd_kill(struct sway_config *config, int argc, char **argv) { | 691 | static 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 | ||
664 | static bool cmd_layout(struct sway_config *config, int argc, char **argv) { | 697 | static 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 | ||
689 | static bool cmd_reload(struct sway_config *config, int argc, char **argv) { | 722 | static 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 | ||
700 | static bool cmd_resize(struct sway_config *config, int argc, char **argv) { | 733 | static 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 | ||
772 | static bool cmd_scratchpad(struct sway_config *config, int argc, char **argv) { | 805 | static 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 | ||
799 | static bool cmd_set(struct sway_config *config, int argc, char **argv) { | 832 | static 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 | ||
812 | static bool _do_split(struct sway_config *config, int argc, char **argv, int layout) { | 845 | static 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 | ||
843 | static bool cmd_split(struct sway_config *config, int argc, char **argv) { | 876 | static 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 | ||
860 | static bool cmd_splitv(struct sway_config *config, int argc, char **argv) { | 893 | static 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 | ||
864 | static bool cmd_splith(struct sway_config *config, int argc, char **argv) { | 897 | static 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 | ||
868 | static bool cmd_log_colors(struct sway_config *config, int argc, char **argv) { | 901 | static 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 | ||
881 | static bool cmd_fullscreen(struct sway_config *config, int argc, char **argv) { | 914 | static 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 | ||
900 | static bool cmd_workspace(struct sway_config *config, int argc, char **argv) { | 933 | static 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 | ||
956 | static bool cmd_ws_auto_back_and_forth(struct sway_config *config, int argc, char **argv) { | 989 | static 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 | ||
995 | static 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 | |||
1047 | static int handler_compare(const void *_a, const void *_b) { | 1029 | static 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 | ||
1061 | bool handle_command(struct sway_config *config, char *exec) { | 1043 | bool 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 | } |
diff --git a/sway/config.c b/sway/config.c index b64dd4b1..119730ca 100644 --- a/sway/config.c +++ b/sway/config.c | |||
@@ -13,6 +13,7 @@ | |||
13 | 13 | ||
14 | struct sway_config *config = NULL; | 14 | struct sway_config *config = NULL; |
15 | 15 | ||
16 | |||
16 | static void free_variable(struct sway_variable *var) { | 17 | static 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 | ||
50 | static 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 | |||
49 | static bool file_exists(const char *path) { | 77 | static 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 | ||
81 | void 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 | |||
107 | static char *get_config_path(void) { | 110 | static 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,34 +213,35 @@ bool load_config(const char *file) { | |||
210 | } | 213 | } |
211 | 214 | ||
212 | bool read_config(FILE *file, bool is_active) { | 215 | bool 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); | ||
228 | line = strip_whitespace(line, &_); | ||
229 | line = strip_comments(line); | 233 | line = strip_comments(line); |
230 | if (!line[0]) { | 234 | if (line[0] == '\0') { |
231 | goto _continue; | 235 | goto _continue; |
232 | } | 236 | } |
233 | if (temp_depth && line[0] == '}') { | 237 | if (line[0] == '}') { |
234 | temp_depth--; | 238 | config->current_mode = default_mode; |
235 | goto _continue; | 239 | goto _continue; |
236 | } | 240 | } |
237 | 241 | ||
238 | // Any command which would require wlc to be initialized | 242 | // Any command which would require wlc to be initialized |
239 | // should be queued for later execution | 243 | // should be queued for later execution |
240 | list_t *args = split_string(line, " "); | 244 | list_t *args = split_string(line, whitespace); |
241 | struct cmd_handler *handler; | 245 | struct cmd_handler *handler; |
242 | if ((handler = find_handler(args->items[0]))) { | 246 | if ((handler = find_handler(args->items[0]))) { |
243 | if (handler->config_type == CMD_KEYBIND) { | 247 | if (handler->config_type == CMD_KEYBIND) { |
@@ -246,11 +250,11 @@ bool read_config(FILE *file, bool is_active) { | |||
246 | sway_log(L_DEBUG, "Deferring command ``%s''", line); | 250 | sway_log(L_DEBUG, "Deferring command ``%s''", line); |
247 | char *cmd = malloc(strlen(line) + 1); | 251 | char *cmd = malloc(strlen(line) + 1); |
248 | strcpy(cmd, line); | 252 | strcpy(cmd, line); |
249 | list_add(temp_config->cmd_queue, cmd); | 253 | list_add(config->cmd_queue, cmd); |
250 | } else if (!temp_depth && !handle_command(temp_config, line)) { | 254 | } else if (!handle_command(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 | ||
279 | char *do_var_replacement(struct sway_config *config, char *str) { | 279 | char *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 | } |
@@ -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..d2b74655 100644 --- a/sway/stringop.c +++ b/sway/stringop.c | |||
@@ -1,34 +1,26 @@ | |||
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> | 10 | const 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. */ |
10 | char *strip_whitespace(char *_str, int *trimmed_start) { | 13 | char *strip_whitespace(char *_str) { |
11 | *trimmed_start = 0; | 14 | int ws = strspn(_str, whitespace); |
12 | if (*_str == '\0') | 15 | int len = strlen(_str) - ws + 1; |
13 | return _str; | 16 | sway_log(L_DEBUG,"%d, %d..",ws,len); |
14 | char *strold = _str; | 17 | char *str = malloc(len); |
15 | while (*_str == ' ' || *_str == '\t') { | 18 | strcpy(str, _str+ws); |
16 | if (*_str == '\t') { | 19 | free(_str); |
17 | *trimmed_start += 8; | ||
18 | } else { | ||
19 | *trimmed_start += 1; | ||
20 | } | ||
21 | _str++; | ||
22 | } | ||
23 | char *str = malloc(strlen(_str) + 1); | ||
24 | strcpy(str, _str); | ||
25 | free(strold); | ||
26 | int i; | ||
27 | for (i = 0; str[i] != '\0'; ++i); | ||
28 | do { | 20 | do { |
29 | i--; | 21 | len--; |
30 | } while (i >= 0 && (str[i] == ' ' || str[i] == '\t')); | 22 | } while (len >= 0 && (str[len] == ' ' || str[len] == '\t')); |
31 | str[i + 1] = '\0'; | 23 | str[len + 1] = '\0'; |
32 | return str; | 24 | return str; |
33 | } | 25 | } |
34 | 26 | ||
@@ -41,7 +33,7 @@ char *strip_comments(char *str) { | |||
41 | } else if (str[i] == '\'' && !in_string) { | 33 | } else if (str[i] == '\'' && !in_string) { |
42 | in_character = !in_character; | 34 | in_character = !in_character; |
43 | } else if (!in_character && !in_string) { | 35 | } else if (!in_character && !in_string) { |
44 | if (str[i] == '#' && i == 0) { | 36 | if (str[i] == '#') { |
45 | str[i] = '\0'; | 37 | str[i] = '\0'; |
46 | break; | 38 | break; |
47 | } | 39 | } |
@@ -51,26 +43,45 @@ char *strip_comments(char *str) { | |||
51 | return str; | 43 | return str; |
52 | } | 44 | } |
53 | 45 | ||
46 | void strip_quotes(char *str) { | ||
47 | bool in_str = false; | ||
48 | bool in_chr = false; | ||
49 | bool escaped = false; | ||
50 | char *end = strchr(str,0); | ||
51 | while (*str) { | ||
52 | if (*str == '\'' && !in_str && !escaped) { | ||
53 | in_chr = !in_chr; | ||
54 | goto shift_over; | ||
55 | } else if (*str == '\"' && !in_chr && !escaped) { | ||
56 | in_str = !in_str; | ||
57 | goto shift_over; | ||
58 | } else if (*str == '\\') { | ||
59 | escaped = !escaped; | ||
60 | ++str; | ||
61 | continue; | ||
62 | } | ||
63 | escaped = false; | ||
64 | ++str; | ||
65 | continue; | ||
66 | shift_over: | ||
67 | memmove(str, str+1, end-- - str); | ||
68 | } | ||
69 | *end = '\0'; | ||
70 | } | ||
71 | |||
54 | list_t *split_string(const char *str, const char *delims) { | 72 | list_t *split_string(const char *str, const char *delims) { |
55 | list_t *res = create_list(); | 73 | list_t *res = create_list(); |
56 | int i, j; | 74 | char *copy = malloc(strlen(str) + 1); |
57 | int len = strlen(str); | 75 | char *token; |
58 | for (i = 0, j = 0; i < len + 1; ++i) { | 76 | strcpy(copy, str); |
59 | if (strchr(delims, str[i]) || i == len) { | 77 | |
60 | if (i - j == 0) { | 78 | token = strtok(copy, delims); |
61 | continue; | 79 | while(token) { |
62 | } | 80 | token = strdup(token); |
63 | char *left = malloc(i - j + 1); | 81 | list_add(res, token); |
64 | memcpy(left, str + j, i - j); | 82 | token = strtok(NULL, delims); |
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 | } | 83 | } |
84 | free(copy); | ||
74 | return res; | 85 | return res; |
75 | } | 86 | } |
76 | 87 | ||
@@ -82,6 +93,60 @@ void free_flat_list(list_t *list) { | |||
82 | list_free(list); | 93 | list_free(list); |
83 | } | 94 | } |
84 | 95 | ||
96 | char **split_args(const char *start, int *argc) { | ||
97 | *argc = 0; | ||
98 | int alloc = 2; | ||
99 | char **parts = malloc(sizeof(char *) * alloc); | ||
100 | bool in_token = false; | ||
101 | bool in_string = false; | ||
102 | bool in_char = false; | ||
103 | bool escaped = false; | ||
104 | const char *end = start; | ||
105 | while (*start) { | ||
106 | if (!in_token) { | ||
107 | start = (end += strspn(end, whitespace)); | ||
108 | in_token = true; | ||
109 | } | ||
110 | if (*end == '"' && !in_char && !escaped) { | ||
111 | in_string = !in_string; | ||
112 | } else if (*end == '\'' && !in_string && !escaped) { | ||
113 | in_char = !in_char; | ||
114 | } else if (*end == '\\') { | ||
115 | escaped = !escaped; | ||
116 | } else if (*end == '\0' || (!in_string && !in_char && !escaped | ||
117 | && strchr(whitespace, *end))) { | ||
118 | goto add_part; | ||
119 | } | ||
120 | if (*end != '\\') { | ||
121 | escaped = false; | ||
122 | } | ||
123 | ++end; | ||
124 | continue; | ||
125 | add_part: | ||
126 | if (end - start > 0) { | ||
127 | char *token = malloc(end - start + 1); | ||
128 | strncpy(token, start, end - start + 1); | ||
129 | token[end - start] = '\0'; | ||
130 | strip_quotes(token); | ||
131 | unescape_string(token); | ||
132 | parts[*argc] = token; | ||
133 | if (++*argc == alloc) { | ||
134 | parts = realloc(parts, (alloc *= 2) * sizeof(char *)); | ||
135 | } | ||
136 | } | ||
137 | in_token = false; | ||
138 | escaped = false; | ||
139 | } | ||
140 | return parts; | ||
141 | } | ||
142 | |||
143 | void free_argv(int argc, char **argv) { | ||
144 | while (--argc) { | ||
145 | free(argv[argc]); | ||
146 | } | ||
147 | free(argv); | ||
148 | } | ||
149 | |||
85 | char *code_strstr(const char *haystack, const char *needle) { | 150 | char *code_strstr(const char *haystack, const char *needle) { |
86 | /* TODO */ | 151 | /* TODO */ |
87 | return strstr(haystack, needle); | 152 | return strstr(haystack, needle); |
@@ -177,7 +242,7 @@ int unescape_string(char *string) { | |||
177 | string[i - 1] = c; | 242 | string[i - 1] = c; |
178 | } | 243 | } |
179 | } | 244 | } |
180 | memmove(string + i, string + i + shift, len - i); | 245 | memmove(string + i, string + i + shift, len - i + 1); |
181 | } | 246 | } |
182 | } | 247 | } |
183 | return len; | 248 | return len; |