summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Drew DeVault <sir@cmpwn.com>2016-03-26 11:51:59 -0400
committerLibravatar Drew DeVault <sir@cmpwn.com>2016-03-26 11:51:59 -0400
commit3b849ce5a6387f2b95936ea225f2047e79a5b0c3 (patch)
treec5b8b0f46b01a681c473a82fff0d0a1412aee094
parentUpdate README.md (diff)
parentAdd config path to error msg (diff)
downloadsway-3b849ce5a6387f2b95936ea225f2047e79a5b0c3.tar.gz
sway-3b849ce5a6387f2b95936ea225f2047e79a5b0c3.tar.zst
sway-3b849ce5a6387f2b95936ea225f2047e79a5b0c3.zip
Merge pull request #544 from mikkeloscar/add-include-command
Add include command
-rw-r--r--include/config.h20
-rw-r--r--sway/commands.c19
-rw-r--r--sway/config.c155
-rw-r--r--sway/main.c4
-rw-r--r--sway/sway.5.txt4
5 files changed, 163 insertions, 39 deletions
diff --git a/include/config.h b/include/config.h
index 9356140d..4bcf55e8 100644
--- a/include/config.h
+++ b/include/config.h
@@ -184,15 +184,27 @@ struct sway_config {
184 bool smart_gaps; 184 bool smart_gaps;
185 int gaps_inner; 185 int gaps_inner;
186 int gaps_outer; 186 int gaps_outer;
187
188 list_t *config_chain;
189 const char *current_config;
187}; 190};
188 191
189/** 192/**
190 * Loads the config from the given path. 193 * Loads the main config from the given path. is_active should be true when
194 * reloading the config.
191 */ 195 */
192bool load_config(const char *file); 196bool load_main_config(const char *path, bool is_active);
193/** Reads the config from the given FILE. 197
198/**
199 * Loads an included config. Can only be used after load_main_config.
194 */ 200 */
195bool read_config(FILE *file, bool is_active); 201bool load_include_configs(const char *path, struct sway_config *config);
202
203/**
204 * Reads the config from the given FILE.
205 */
206bool read_config(FILE *file, struct sway_config *config);
207
196/** 208/**
197 * Free config struct 209 * Free config struct
198 */ 210 */
diff --git a/sway/commands.c b/sway/commands.c
index 26fa771e..e251f167 100644
--- a/sway/commands.c
+++ b/sway/commands.c
@@ -55,6 +55,7 @@ static sway_cmd cmd_font;
55static sway_cmd cmd_for_window; 55static sway_cmd cmd_for_window;
56static sway_cmd cmd_fullscreen; 56static sway_cmd cmd_fullscreen;
57static sway_cmd cmd_gaps; 57static sway_cmd cmd_gaps;
58static sway_cmd cmd_include;
58static sway_cmd cmd_input; 59static sway_cmd cmd_input;
59static sway_cmd cmd_kill; 60static sway_cmd cmd_kill;
60static sway_cmd cmd_layout; 61static sway_cmd cmd_layout;
@@ -1141,6 +1142,19 @@ static struct cmd_results *input_cmd_tap(int argc, char **argv) {
1141 return cmd_results_new(CMD_SUCCESS, NULL, NULL); 1142 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
1142} 1143}
1143 1144
1145static struct cmd_results *cmd_include(int argc, char **argv) {
1146 struct cmd_results *error = NULL;
1147 if ((error = checkarg(argc, "include", EXPECTED_EQUAL_TO, 1))) {
1148 return error;
1149 }
1150
1151 if (!load_include_configs(argv[0], config)) {
1152 return cmd_results_new(CMD_INVALID, "include", "Failed to include sub configuration file: %s", argv[0]);
1153 }
1154
1155 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
1156}
1157
1144static struct cmd_results *cmd_input(int argc, char **argv) { 1158static struct cmd_results *cmd_input(int argc, char **argv) {
1145 struct cmd_results *error = NULL; 1159 struct cmd_results *error = NULL;
1146 if ((error = checkarg(argc, "input", EXPECTED_AT_LEAST, 2))) { 1160 if ((error = checkarg(argc, "input", EXPECTED_AT_LEAST, 2))) {
@@ -1541,7 +1555,9 @@ static struct cmd_results *cmd_reload(int argc, char **argv) {
1541 if ((error = checkarg(argc, "reload", EXPECTED_EQUAL_TO, 0))) { 1555 if ((error = checkarg(argc, "reload", EXPECTED_EQUAL_TO, 0))) {
1542 return error; 1556 return error;
1543 } 1557 }
1544 if (!load_config(NULL)) return cmd_results_new(CMD_FAILURE, "reload", "Error(s) reloading config."); 1558 if (!load_main_config(config->current_config, true)) {
1559 return cmd_results_new(CMD_FAILURE, "reload", "Error(s) reloading config.");
1560 }
1545 1561
1546 load_swaybars(); 1562 load_swaybars();
1547 1563
@@ -2053,6 +2069,7 @@ static struct cmd_handler handlers[] = {
2053 { "for_window", cmd_for_window }, 2069 { "for_window", cmd_for_window },
2054 { "fullscreen", cmd_fullscreen }, 2070 { "fullscreen", cmd_fullscreen },
2055 { "gaps", cmd_gaps }, 2071 { "gaps", cmd_gaps },
2072 { "include", cmd_include },
2056 { "input", cmd_input }, 2073 { "input", cmd_input },
2057 { "kill", cmd_kill }, 2074 { "kill", cmd_kill },
2058 { "layout", cmd_layout }, 2075 { "layout", cmd_layout },
diff --git a/sway/config.c b/sway/config.c
index a5fdf850..c30c1767 100644
--- a/sway/config.c
+++ b/sway/config.c
@@ -2,6 +2,7 @@
2#include <stdbool.h> 2#include <stdbool.h>
3#include <stdlib.h> 3#include <stdlib.h>
4#include <unistd.h> 4#include <unistd.h>
5#include <libgen.h>
5#include <wordexp.h> 6#include <wordexp.h>
6#include <sys/types.h> 7#include <sys/types.h>
7#include <sys/wait.h> 8#include <sys/wait.h>
@@ -126,6 +127,7 @@ void free_config(struct sway_config *config) {
126 list_free(config->output_configs); 127 list_free(config->output_configs);
127 128
128 list_free(config->active_bar_modifiers); 129 list_free(config->active_bar_modifiers);
130 free_flat_list(config->config_chain);
129 free(config->font); 131 free(config->font);
130 free(config); 132 free(config);
131} 133}
@@ -175,6 +177,9 @@ static void config_defaults(struct sway_config *config) {
175 config->gaps_outer = 0; 177 config->gaps_outer = 0;
176 178
177 config->active_bar_modifiers = create_list(); 179 config->active_bar_modifiers = create_list();
180
181 config->config_chain = create_list();
182 config->current_config = NULL;
178} 183}
179 184
180static int compare_modifiers(const void *left, const void *right) { 185static int compare_modifiers(const void *left, const void *right) {
@@ -237,16 +242,7 @@ static char *get_config_path(void) {
237 return NULL; // Not reached 242 return NULL; // Not reached
238} 243}
239 244
240bool load_config(const char *file) { 245static bool load_config(const char *path, struct sway_config *config) {
241 input_init();
242
243 char *path;
244 if (file != NULL) {
245 path = strdup(file);
246 } else {
247 path = get_config_path();
248 }
249
250 sway_log(L_INFO, "Loading config from %s", path); 246 sway_log(L_INFO, "Loading config from %s", path);
251 247
252 if (path == NULL) { 248 if (path == NULL) {
@@ -257,20 +253,12 @@ bool load_config(const char *file) {
257 FILE *f = fopen(path, "r"); 253 FILE *f = fopen(path, "r");
258 if (!f) { 254 if (!f) {
259 sway_log(L_ERROR, "Unable to open %s for reading", path); 255 sway_log(L_ERROR, "Unable to open %s for reading", path);
260 free(path);
261 return false; 256 return false;
262 } 257 }
263 free(path);
264 258
265 bool config_load_success; 259 bool config_load_success = read_config(f, config);
266 if (config) {
267 config_load_success = read_config(f, true);
268 } else {
269 config_load_success = read_config(f, false);
270 }
271 fclose(f); 260 fclose(f);
272 261
273 update_active_bar_modifiers();
274 262
275 if (!config_load_success) { 263 if (!config_load_success) {
276 sway_log(L_ERROR, "Error(s) loading config!"); 264 sway_log(L_ERROR, "Error(s) loading config!");
@@ -279,17 +267,129 @@ bool load_config(const char *file) {
279 return true; 267 return true;
280} 268}
281 269
282bool read_config(FILE *file, bool is_active) { 270bool load_main_config(const char *file, bool is_active) {
271 input_init();
272
273 char *path;
274 if (file != NULL) {
275 path = strdup(file);
276 } else {
277 path = get_config_path();
278 }
279
283 struct sway_config *old_config = config; 280 struct sway_config *old_config = config;
284 config = calloc(1, sizeof(struct sway_config)); 281 config = calloc(1, sizeof(struct sway_config));
285 282
286 config_defaults(config); 283 config_defaults(config);
287 config->reading = true;
288 if (is_active) { 284 if (is_active) {
289 sway_log(L_DEBUG, "Performing configuration file reload"); 285 sway_log(L_DEBUG, "Performing configuration file reload");
290 config->reloading = true; 286 config->reloading = true;
291 config->active = true; 287 config->active = true;
292 } 288 }
289
290 config->current_config = path;
291 list_add(config->config_chain, path);
292
293 config->reading = true;
294 bool success = load_config(path, config);
295
296 if (is_active) {
297 config->reloading = false;
298 }
299
300 if (old_config) {
301 free_config(old_config);
302 }
303 config->reading = false;
304
305 if (success) {
306 update_active_bar_modifiers();
307 }
308
309 return success;
310}
311
312static bool load_include_config(const char *path, const char *parent_dir, struct sway_config *config) {
313 // save parent config
314 const char *parent_config = config->current_config;
315
316 char *full_path = strdup(path);
317 int len = strlen(path);
318 if (len >= 1 && path[0] != '/') {
319 len = len + strlen(parent_dir) + 2;
320 full_path = malloc(len * sizeof(char));
321 snprintf(full_path, len, "%s/%s", parent_dir, path);
322 }
323
324 char *real_path = realpath(full_path, NULL);
325 free(full_path);
326
327 // check if config has already been included
328 int j;
329 for (j = 0; j < config->config_chain->length; ++j) {
330 char *old_path = config->config_chain->items[j];
331 if (strcmp(real_path, old_path) == 0) {
332 sway_log(L_DEBUG, "%s already included once, won't be included again.", real_path);
333 free(real_path);
334 return false;
335 }
336 }
337
338 config->current_config = real_path;
339 list_add(config->config_chain, real_path);
340 int index = config->config_chain->length - 1;
341
342 if (!load_config(real_path, config)) {
343 free(real_path);
344 config->current_config = parent_config;
345 list_del(config->config_chain, index);
346 return false;
347 }
348
349 // restore current_config
350 config->current_config = parent_config;
351 return true;
352}
353
354bool load_include_configs(const char *path, struct sway_config *config) {
355 char *wd = getcwd(NULL, 0);
356 char *parent_path = strdup(config->current_config);
357 const char *parent_dir = dirname(parent_path);
358
359 if (chdir(parent_dir) < 0) {
360 free(parent_path);
361 free(wd);
362 return false;
363 }
364
365 wordexp_t p;
366
367 if (wordexp(path, &p, 0) < 0) {
368 free(parent_path);
369 free(wd);
370 return false;
371 }
372
373 char **w = p.we_wordv;
374 size_t i;
375 for (i = 0; i < p.we_wordc; ++i) {
376 load_include_config(w[i], parent_dir, config);
377 }
378 free(parent_path);
379 wordfree(&p);
380
381 // restore wd
382 if (chdir(wd) < 0) {
383 free(wd);
384 sway_log(L_ERROR, "failed to restore working directory");
385 return false;
386 }
387
388 free(wd);
389 return true;
390}
391
392bool read_config(FILE *file, struct sway_config *config) {
293 bool success = true; 393 bool success = true;
294 enum cmd_status block = CMD_BLOCK_END; 394 enum cmd_status block = CMD_BLOCK_END;
295 395
@@ -307,8 +407,8 @@ bool read_config(FILE *file, bool is_active) {
307 switch(res->status) { 407 switch(res->status) {
308 case CMD_FAILURE: 408 case CMD_FAILURE:
309 case CMD_INVALID: 409 case CMD_INVALID:
310 sway_log(L_ERROR, "Error on line %i '%s': %s", line_number, line, 410 sway_log(L_ERROR, "Error on line %i '%s': %s (%s)", line_number, line,
311 res->error); 411 res->error, config->current_config);
312 success = false; 412 success = false;
313 break; 413 break;
314 414
@@ -386,15 +486,6 @@ bool read_config(FILE *file, bool is_active) {
386 free(res); 486 free(res);
387 } 487 }
388 488
389 if (is_active) {
390 config->reloading = false;
391 arrange_windows(&root_container, -1, -1);
392 }
393 if (old_config) {
394 free_config(old_config);
395 }
396
397 config->reading = false;
398 return success; 489 return success;
399} 490}
400 491
diff --git a/sway/main.c b/sway/main.c
index c4a5d497..4aaac556 100644
--- a/sway/main.c
+++ b/sway/main.c
@@ -206,11 +206,11 @@ int main(int argc, char **argv) {
206 init_layout(); 206 init_layout();
207 207
208 if (validate) { 208 if (validate) {
209 bool valid = load_config(config_path); 209 bool valid = load_main_config(config_path, false);
210 return valid ? 0 : 1; 210 return valid ? 0 : 1;
211 } 211 }
212 212
213 if (!load_config(config_path)) { 213 if (!load_main_config(config_path, false)) {
214 sway_terminate(EXIT_FAILURE); 214 sway_terminate(EXIT_FAILURE);
215 } 215 }
216 216
diff --git a/sway/sway.5.txt b/sway/sway.5.txt
index e73beb81..d626df48 100644
--- a/sway/sway.5.txt
+++ b/sway/sway.5.txt
@@ -215,6 +215,10 @@ or triggered at runtime.
215**workspace_layout** <default|stacking|tabbed>:: 215**workspace_layout** <default|stacking|tabbed>::
216 Specifies the start layout for new workspaces. 216 Specifies the start layout for new workspaces.
217 217
218**include** <path>::
219 Includes a sub config file by _path_. _path_ can be either a full path or a
220 path relative to the parent config.
221
218Criteria 222Criteria
219-------- 223--------
220 224