Commit 38314f607eb9
tarball3 files changed+63-15
@@ -207,10 +207,11 @@ impl State {
207207
}208208
}209209
210
- /// Swaps in a freshly parsed config. A broken file leaves the running211
- /// config untouched.210
+ /// Swaps in a freshly parsed config. A file that is not TOML leaves the211
+ /// running config untouched.212212
pub fn reload(&mut self) -> Result<(), String> {213
- let config = Config::load(self.settings.path.as_deref()).map_err(|e| e.to_string())?;213
+ let loaded = Config::load(self.settings.path.as_deref()).map_err(|e| e.to_string())?;214
+ let config = warn_config(loaded);214215
let keyboard_changed = config.keyboard != self.settings.config.keyboard;215216
self.settings.binds = Binds::new(&config);216217
self.wm.layout.gaps = crate::state::gaps(&config);@@ -223,3 +224,10 @@ impl State {
223224
Ok(())224225
}225226
}227
+228
+pub fn warn_config(loaded: monolith_config::Loaded) -> Config {229
+ for w in &loaded.warnings {230
+ tracing::warn!("config: {w}");231
+ }232
+ loaded.config233
+}@@ -116,11 +116,26 @@ fn main() -> ExitCode {
116116
}117117
Some(Cmd::Subscribe) => return ipc::client(Request::Subscribe {}),118118
};119
- let filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info"));119
+ let backend = match backend {120
+ Backend::Auto if std::env::var_os("WAYLAND_DISPLAY").is_some() => Backend::Nested,121
+ Backend::Auto => Backend::Drm,122
+ b => b,123
+ };124
+ let filter = || EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info"));120125
let fmt = tracing_subscriber::fmt::layer()121126
.with_writer(std::io::stderr)122127
.with_ansi(std::io::IsTerminal::is_terminal(&std::io::stderr()))123
- .with_filter(filter);128
+ .with_filter(filter());129
+ let log_path = log_file(backend);130
+ let file = log_path.as_ref().and_then(|p| {131
+ let file = std::fs::File::create(p).ok()?;132
+ Some(133
+ tracing_subscriber::fmt::layer()134
+ .with_writer(std::sync::Mutex::new(file))135
+ .with_ansi(false)136
+ .with_filter(filter()),137
+ )138
+ });124139
#[cfg(feature = "spans")]125140
let slow = slow_spans::SlowSpans::from_env();126141
#[cfg(feature = "spans")]@@ -129,14 +144,16 @@ fn main() -> ExitCode {
129144
let spans = Some(slow.with_filter(tracing_subscriber::filter::LevelFilter::TRACE));130145
#[cfg(not(feature = "spans"))]131146
let spans: Option<tracing_subscriber::layer::Identity> = None;132
- tracing_subscriber::registry().with(fmt).with(spans).init();147
+ tracing_subscriber::registry()148
+ .with(fmt)149
+ .with(file)150
+ .with(spans)151
+ .init();152
+ if let Some(p) = &log_path {153
+ tracing::info!(path = %p.display(), "logging to a file");154
+ }133155
#[cfg(feature = "spans")]134156
tracing::info!("logging spans slower than {threshold_us} us");135
- let backend = match backend {136
- Backend::Auto if std::env::var_os("WAYLAND_DISPLAY").is_some() => Backend::Nested,137
- Backend::Auto => Backend::Drm,138
- b => b,139
- };140157
match run(config, backend, &program) {141158
Ok(()) => ExitCode::SUCCESS,142159
Err(e) => {@@ -146,6 +163,24 @@ fn main() -> ExitCode {
146163
}147164
}148165
166
+/// `$XDG_STATE_HOME/monolith/monolith.log`, with the previous run kept as167
+/// `monolith.old.log`. Nested runs log beside it, so testing one does not168
+/// overwrite the log of the session hosting it.169
+fn log_file(backend: Backend) -> Option<PathBuf> {170
+ let dir = std::env::var_os("XDG_STATE_HOME")171
+ .map(PathBuf::from)172
+ .or_else(|| std::env::var_os("HOME").map(|h| PathBuf::from(h).join(".local/state")))?173
+ .join("monolith");174
+ std::fs::create_dir_all(&dir).ok()?;175
+ let name = match backend {176
+ Backend::Nested => "nested",177
+ _ => "monolith",178
+ };179
+ let path = dir.join(format!("{name}.log"));180
+ let _ = std::fs::rename(&path, dir.join(format!("{name}.old.log")));181
+ Some(path)182
+}183
+149184
/// Puts the compositor thread on SCHED_RR so a busy desktop cannot delay a150185
/// frame. Reset-on-fork keeps threads and programs it starts off realtime.151186
/// The NixOS capability wrapper raises CAP_SYS_NICE as an ambient capability,@@ -102,10 +102,15 @@ impl State {
102102
) -> Result<Self, Box<dyn std::error::Error>> {103103
let dh = display.handle();104104
let config_path = config_path.or_else(Config::path);105
- let config = Config::load(config_path.as_deref()).unwrap_or_else(|e| {106
- tracing::error!("config: {e}, using the built-in default");107
- Config::parse(monolith_config::DEFAULT).expect("the default config parses")108
- });105
+ let config = match Config::load(config_path.as_deref()) {106
+ Ok(loaded) => crate::commands::warn_config(loaded),107
+ Err(e) => {108
+ tracing::error!("config: {e}, using the built-in default");109
+ Config::parse(monolith_config::DEFAULT)110
+ .expect("the default config parses")111
+ .config112
+ }113
+ };109114
let renderer = match gpu {110115
Some(node) => VulkanRenderer::for_node(node)?,111116
None => VulkanRenderer::new()?,