use std::path::Path;
use clap::Parser;
use flow_wm::config::{
WindowRulesConfig, dirs, init_config_dir, load_app_config, load_default_rules,
load_rules_config,
};
use flow_wm::daemon::FlowWM;
use flow_wm::logging;
#[cfg(debug_assertions)]
use flow_wm::registry::desktop;
#[derive(Parser)]
#[command(name = "flowd", version, about = "FlowWM daemon")]
#[command(propagate_version = true)]
struct Args {
#[arg(long)]
config: Option<String>,
#[arg(long, value_name = "PATH")]
log_file: Option<String>,
#[cfg(debug_assertions)]
#[arg(long)]
desktop: Option<String>,
}
fn main() {
let args = Args::parse();
logging::init(args.log_file.as_deref().map(Path::new));
if let Err(e) = run(args) {
log::error!("flowd: fatal error: {e}");
std::process::exit(1);
}
}
fn run(args: Args) -> Result<(), String> {
#[cfg(debug_assertions)]
if let Some(ref name) = args.desktop {
desktop::switch_to_desktop(name)?;
}
let config_dir = dirs::resolve_config_dir(args.config.as_deref().map(Path::new));
log::info!("using config directory: {}", config_dir.display());
init_config_dir(&config_dir)?;
let app_config = load_app_config(&dirs::user_app_config_path_in(&config_dir))
.map_err(|e| format!("flowd: {e}"))?;
let user_rules =
load_rules_config(&dirs::user_rules_path_in(&config_dir)).unwrap_or_else(|e| {
log::warn!("flowd: {e}; using default window rules");
WindowRulesConfig::default()
});
let default_rules = load_default_rules();
#[cfg(debug_assertions)]
let desktop_name = args.desktop.clone();
#[cfg(not(debug_assertions))]
let desktop_name = None;
let mut flow = FlowWM::new(
app_config,
user_rules,
default_rules,
config_dir,
desktop_name,
)?;
flow.run();
flow.rescue_stranded_windows();
Ok(())
}