aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIvan Molodetskikh <yalterz@gmail.com>2024-09-02 13:10:45 +0300
committerIvan Molodetskikh <yalterz@gmail.com>2024-09-02 13:10:45 +0300
commit4b7c16b04a7c80f5f9b6fcbc4a1d8c9448dffbdb (patch)
treec19a52b12720a83a6a06501d5295e35da43065be
parentaafd5ab70ff7031e8fa448d13a217ab66b6a4483 (diff)
downloadniri-4b7c16b04a7c80f5f9b6fcbc4a1d8c9448dffbdb.tar.gz
niri-4b7c16b04a7c80f5f9b6fcbc4a1d8c9448dffbdb.tar.bz2
niri-4b7c16b04a7c80f5f9b6fcbc4a1d8c9448dffbdb.zip
Read config from /etc/niri/config.kdl too
-rw-r--r--src/main.rs122
-rw-r--r--src/ui/config_error_notification.rs3
-rw-r--r--wiki/Configuration:-Overview.md4
3 files changed, 73 insertions, 56 deletions
diff --git a/src/main.rs b/src/main.rs
index ad201b2d..bb22e071 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -90,10 +90,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
Sub::Validate { config } => {
tracy_client::Client::start();
- let path = config
- .or_else(env_config_path)
- .or_else(default_config_path)
- .expect("error getting config path");
+ let (path, _, _) = config_path(config);
Config::load(&path)?;
info!("config is valid");
return Ok(());
@@ -114,56 +111,50 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
// Load the config.
let mut config_created = false;
- let path = cli.config.or_else(env_config_path);
+ let (path, watch_path, create_default) = config_path(cli.config);
env::remove_var("NIRI_CONFIG");
- let path = path.or_else(|| {
- let default_path = default_config_path()?;
- let default_parent = default_path.parent().unwrap();
-
- if let Err(err) = fs::create_dir_all(default_parent) {
- warn!(
- "error creating config directories {:?}: {err:?}",
- default_parent
- );
- return Some(default_path);
- }
-
- // Create the config and fill it with the default config if it doesn't exist.
- let new_file = File::options()
- .read(true)
- .write(true)
- .create_new(true)
- .open(&default_path);
- match new_file {
- Ok(mut new_file) => {
- let default = include_bytes!("../resources/default-config.kdl");
- match new_file.write_all(default) {
- Ok(()) => {
- config_created = true;
- info!("wrote default config to {:?}", &default_path);
- }
- Err(err) => {
- warn!("error writing config file at {:?}: {err:?}", &default_path)
+ if create_default {
+ let default_parent = path.parent().unwrap();
+
+ match fs::create_dir_all(default_parent) {
+ Ok(()) => {
+ // Create the config and fill it with the default config if it doesn't exist.
+ let new_file = File::options()
+ .read(true)
+ .write(true)
+ .create_new(true)
+ .open(&path);
+ match new_file {
+ Ok(mut new_file) => {
+ let default = include_bytes!("../resources/default-config.kdl");
+ match new_file.write_all(default) {
+ Ok(()) => {
+ config_created = true;
+ info!("wrote default config to {:?}", &path);
+ }
+ Err(err) => {
+ warn!("error writing config file at {:?}: {err:?}", &path)
+ }
+ }
}
+ Err(err) if err.kind() == io::ErrorKind::AlreadyExists => {}
+ Err(err) => warn!("error creating config file at {:?}: {err:?}", &path),
}
}
- Err(err) if err.kind() == io::ErrorKind::AlreadyExists => {}
- Err(err) => warn!("error creating config file at {:?}: {err:?}", &default_path),
+ Err(err) => {
+ warn!(
+ "error creating config directories {:?}: {err:?}",
+ default_parent
+ );
+ }
}
-
- Some(default_path)
- });
+ }
let mut config_errored = false;
- let mut config = path
- .as_deref()
- .and_then(|path| match Config::load(path) {
- Ok(config) => Some(config),
- Err(err) => {
- warn!("{err:?}");
- config_errored = true;
- None
- }
+ let mut config = Config::load(&path)
+ .map_err(|err| {
+ warn!("{err:?}");
+ config_errored = true;
})
.unwrap_or_default();
@@ -231,19 +222,17 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
}
// Set up config file watcher.
- let _watcher = if let Some(path) = path.clone() {
+ let _watcher = {
let (tx, rx) = calloop::channel::sync_channel(1);
- let watcher = Watcher::new(path.clone(), tx);
+ let watcher = Watcher::new(watch_path.clone(), tx);
event_loop
.handle()
.insert_source(rx, move |event, _, state| match event {
- calloop::channel::Event::Msg(()) => state.reload_config(path.clone()),
+ calloop::channel::Event::Msg(()) => state.reload_config(watch_path.clone()),
calloop::channel::Event::Closed => (),
})
.unwrap();
- Some(watcher)
- } else {
- None
+ watcher
};
// Spawn commands from cli and auto-start.
@@ -335,6 +324,33 @@ fn default_config_path() -> Option<PathBuf> {
Some(path)
}
+fn system_config_path() -> PathBuf {
+ PathBuf::from("/etc/niri/config.kdl")
+}
+
+/// Resolves and returns the config path to load, the config path to watch, and whether to create
+/// the default config at the path to load.
+fn config_path(cli_path: Option<PathBuf>) -> (PathBuf, PathBuf, bool) {
+ if let Some(explicit) = cli_path.or_else(env_config_path) {
+ return (explicit.clone(), explicit, false);
+ }
+
+ let system_path = system_config_path();
+ if let Some(path) = default_config_path() {
+ if path.exists() {
+ return (path.clone(), path, true);
+ }
+
+ if system_path.exists() {
+ (system_path, path, false)
+ } else {
+ (path.clone(), path, true)
+ }
+ } else {
+ (system_path.clone(), system_path, false)
+ }
+}
+
fn notify_fd() -> anyhow::Result<()> {
let fd = match env::var("NOTIFY_FD") {
Ok(notify_fd) => notify_fd.parse()?,
diff --git a/src/ui/config_error_notification.rs b/src/ui/config_error_notification.rs
index aa218c91..c4ca3b69 100644
--- a/src/ui/config_error_notification.rs
+++ b/src/ui/config_error_notification.rs
@@ -60,7 +60,8 @@ impl ConfigErrorNotification {
Animation::new(from, to, 0., c.animations.config_notification_open_close.0)
}
- pub fn show_created(&mut self, created_path: Option<PathBuf>) {
+ pub fn show_created(&mut self, created_path: PathBuf) {
+ let created_path = Some(created_path);
if self.created_path != created_path {
self.created_path = created_path;
self.buffers.borrow_mut().clear();
diff --git a/wiki/Configuration:-Overview.md b/wiki/Configuration:-Overview.md
index eedcc560..5988ac7c 100644
--- a/wiki/Configuration:-Overview.md
+++ b/wiki/Configuration:-Overview.md
@@ -13,8 +13,8 @@ You can find documentation for various sections of the config on these wiki page
### Loading
-Niri will load configuration from `$XDG_CONFIG_HOME/niri/config.kdl` or `~/.config/niri/config.kdl`.
-If that file is missing, niri will create it with the contents of [the default configuration file](https://github.com/YaLTeR/niri/blob/main/resources/default-config.kdl).
+Niri will load configuration from `$XDG_CONFIG_HOME/niri/config.kdl` or `~/.config/niri/config.kdl`, falling back to `/etc/niri/config.kdl`.
+If both of these files are missing, niri will create `$XDG_CONFIG_HOME/niri/config.kdl` with the contents of [the default configuration file](https://github.com/YaLTeR/niri/blob/main/resources/default-config.kdl), which are embedded into the niri binary at build time.
Please use the default configuration file as the starting point for your custom configuration.
The configuration is live-reloaded.