summaryrefslogtreecommitdiffstats
path: root/sway/config.c
diff options
context:
space:
mode:
authorLibravatar Mikkel Oscar Lyderik <mikkeloscar@gmail.com>2016-03-26 12:31:53 +0100
committerLibravatar Mikkel Oscar Lyderik <mikkeloscar@gmail.com>2016-03-26 16:37:50 +0100
commit71a5350b681e022e9738b50f2977ddb529110bfb (patch)
tree4c199980a9f80c07d69130a72402a5cfe2a8a63f /sway/config.c
parentUpdate README.md (diff)
downloadsway-71a5350b681e022e9738b50f2977ddb529110bfb.tar.gz
sway-71a5350b681e022e9738b50f2977ddb529110bfb.tar.zst
sway-71a5350b681e022e9738b50f2977ddb529110bfb.zip
Implement include command
The include command (`include <path>`) makes it possible to include sub config files from the main config file (or from within other sub config files). The include command uses the following rules for including config files: * the `path` can be either a full path or a path that is relative to the parent config. Shell expansion is supported, so it's possible to do `include ~/.config/sway.d/*`. * The same config file can only be included once (to prevent include cycles). If a config is included multiple times it will just be ignored after it has been included once. * Including a sub config file is the same as inserting the content of that file into the parent config, thus rules about overwriting bindsyms etc. works the same as for a single config. Implement #542
Diffstat (limited to 'sway/config.c')
-rw-r--r--sway/config.c151
1 files changed, 121 insertions, 30 deletions
diff --git a/sway/config.c b/sway/config.c
index a5fdf850..d54ce213 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
@@ -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