mirror of
https://github.com/swaywm/sway.git
synced 2026-04-18 06:46:56 -04:00
config: add include_one directive
Adds include_one <pattern1> <pattern2>, which loads all files matching pattern1, then loads files from pattern2 only if their basename was not already loaded from pattern1. This allows user configs in ~/.config/sway/conf.d/ to shadow distro-provided defaults in /etc/sway/conf.d/ by filename without completely overriding the include path — a common pain point for packagers on NixOS, Fedora, and similar distributions. Edge cases handled: - pattern1 matches nothing: all pattern2 files load normally - Same basename in both: pattern1 file wins, pattern2 skipped - Neither pattern matches: silently succeeds (matches include behavior)
This commit is contained in:
parent
6d25b100a2
commit
d5940c1cc8
7 changed files with 96 additions and 0 deletions
|
|
@ -145,6 +145,7 @@ sway_cmd cmd_fullscreen;
|
||||||
sway_cmd cmd_gaps;
|
sway_cmd cmd_gaps;
|
||||||
sway_cmd cmd_hide_edge_borders;
|
sway_cmd cmd_hide_edge_borders;
|
||||||
sway_cmd cmd_include;
|
sway_cmd cmd_include;
|
||||||
|
sway_cmd cmd_include_one;
|
||||||
sway_cmd cmd_inhibit_idle;
|
sway_cmd cmd_inhibit_idle;
|
||||||
sway_cmd cmd_input;
|
sway_cmd cmd_input;
|
||||||
sway_cmd cmd_seat;
|
sway_cmd cmd_seat;
|
||||||
|
|
|
||||||
|
|
@ -621,6 +621,14 @@ bool load_main_config(const char *path, bool is_active, bool validating);
|
||||||
void load_include_configs(const char *path, struct sway_config *config,
|
void load_include_configs(const char *path, struct sway_config *config,
|
||||||
struct swaynag_instance *swaynag);
|
struct swaynag_instance *swaynag);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads included configs using basename-based shadowing.
|
||||||
|
* Files from pattern1 are always loaded. Files from pattern2 are loaded
|
||||||
|
* only if their basename was not already loaded from pattern1.
|
||||||
|
*/
|
||||||
|
void load_include_one_configs(const char *pattern1, const char *pattern2,
|
||||||
|
struct sway_config *config, struct swaynag_instance *swaynag);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads the config from the given FILE.
|
* Reads the config from the given FILE.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -103,6 +103,7 @@ static const struct cmd_handler handlers[] = {
|
||||||
static const struct cmd_handler config_handlers[] = {
|
static const struct cmd_handler config_handlers[] = {
|
||||||
{ "default_orientation", cmd_default_orientation },
|
{ "default_orientation", cmd_default_orientation },
|
||||||
{ "include", cmd_include },
|
{ "include", cmd_include },
|
||||||
|
{ "include_one", cmd_include_one },
|
||||||
{ "primary_selection", cmd_primary_selection },
|
{ "primary_selection", cmd_primary_selection },
|
||||||
{ "swaybg_command", cmd_swaybg_command },
|
{ "swaybg_command", cmd_swaybg_command },
|
||||||
{ "swaynag_command", cmd_swaynag_command },
|
{ "swaynag_command", cmd_swaynag_command },
|
||||||
|
|
|
||||||
12
sway/commands/include_one.c
Normal file
12
sway/commands/include_one.c
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
#include "sway/commands.h"
|
||||||
|
#include "sway/config.h"
|
||||||
|
|
||||||
|
struct cmd_results *cmd_include_one(int argc, char **argv) {
|
||||||
|
struct cmd_results *error = NULL;
|
||||||
|
if ((error = checkarg(argc, "include_one", EXPECTED_EQUAL_TO, 2))) {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
load_include_one_configs(argv[0], argv[1], config,
|
||||||
|
&config->swaynag_config_errors);
|
||||||
|
return cmd_results_new(CMD_SUCCESS, NULL);
|
||||||
|
}
|
||||||
|
|
@ -623,6 +623,72 @@ cleanup:
|
||||||
free(wd);
|
free(wd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void load_include_one_configs(const char *pattern1, const char *pattern2,
|
||||||
|
struct sway_config *config, struct swaynag_instance *swaynag) {
|
||||||
|
char *wd = getcwd(NULL, 0);
|
||||||
|
if (!wd) {
|
||||||
|
sway_log(SWAY_ERROR, "include_one: failed to get working directory");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
char *parent_path = strdup(config->current_config_path);
|
||||||
|
const char *parent_dir = dirname(parent_path);
|
||||||
|
if (chdir(parent_dir) < 0) {
|
||||||
|
sway_log(SWAY_ERROR, "include_one: failed to change working directory");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
list_t *loaded_basenames = create_list();
|
||||||
|
if (!loaded_basenames) {
|
||||||
|
sway_log(SWAY_ERROR, "include_one: failed to allocate list");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
wordexp_t p;
|
||||||
|
if (wordexp(pattern1, &p, 0) == 0) {
|
||||||
|
char **w = p.we_wordv;
|
||||||
|
for (size_t i = 0; i < p.we_wordc; i++) {
|
||||||
|
if (load_include_config(w[i], config, swaynag)) {
|
||||||
|
char *tmp = strdup(w[i]);
|
||||||
|
list_add(loaded_basenames, strdup(basename(tmp)));
|
||||||
|
free(tmp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
wordfree(&p);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wordexp(pattern2, &p, 0) == 0) {
|
||||||
|
char **w = p.we_wordv;
|
||||||
|
for (size_t i = 0; i < p.we_wordc; i++) {
|
||||||
|
char *tmp = strdup(w[i]);
|
||||||
|
char *base = basename(tmp);
|
||||||
|
bool already_loaded = false;
|
||||||
|
for (int j = 0; j < loaded_basenames->length; j++) {
|
||||||
|
if (strcmp(loaded_basenames->items[j], base) == 0) {
|
||||||
|
already_loaded = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!already_loaded) {
|
||||||
|
load_include_config(w[i], config, swaynag);
|
||||||
|
}
|
||||||
|
free(tmp);
|
||||||
|
}
|
||||||
|
wordfree(&p);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < loaded_basenames->length; i++) {
|
||||||
|
free(loaded_basenames->items[i]);
|
||||||
|
}
|
||||||
|
list_free(loaded_basenames);
|
||||||
|
|
||||||
|
if (chdir(wd) < 0) {
|
||||||
|
sway_log(SWAY_ERROR, "failed to change working directory");
|
||||||
|
}
|
||||||
|
cleanup:
|
||||||
|
free(parent_path);
|
||||||
|
free(wd);
|
||||||
|
}
|
||||||
|
|
||||||
void run_deferred_commands(void) {
|
void run_deferred_commands(void) {
|
||||||
if (!config->cmd_queue->length) {
|
if (!config->cmd_queue->length) {
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -76,6 +76,7 @@ sway_sources = files(
|
||||||
'commands/max_render_time.c',
|
'commands/max_render_time.c',
|
||||||
'commands/opacity.c',
|
'commands/opacity.c',
|
||||||
'commands/include.c',
|
'commands/include.c',
|
||||||
|
'commands/include_one.c',
|
||||||
'commands/input.c',
|
'commands/input.c',
|
||||||
'commands/layout.c',
|
'commands/layout.c',
|
||||||
'commands/mode.c',
|
'commands/mode.c',
|
||||||
|
|
|
||||||
|
|
@ -72,6 +72,13 @@ The following commands may only be used in the configuration file.
|
||||||
*wordexp*(3) for details). The same include file can only be included once;
|
*wordexp*(3) for details). The same include file can only be included once;
|
||||||
subsequent attempts will be ignored.
|
subsequent attempts will be ignored.
|
||||||
|
|
||||||
|
*include_one* <pattern1> <pattern2>
|
||||||
|
Include files from _pattern1_. Then include files from _pattern2_ only
|
||||||
|
if a file with the same basename was not already included from
|
||||||
|
_pattern1_. Both patterns expand shell syntax (see *wordexp*(3) for
|
||||||
|
details). This allows user configs to shadow distro-provided defaults
|
||||||
|
by filename.
|
||||||
|
|
||||||
*swaybg_command* <command>
|
*swaybg_command* <command>
|
||||||
Executes custom background _command_. Default is _swaybg_. Refer to
|
Executes custom background _command_. Default is _swaybg_. Refer to
|
||||||
*sway-output*(5) for more information.
|
*sway-output*(5) for more information.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue