use std::path::PathBuf;
use clap::{Parser, Subcommand};
use crate::config;
use crate::device;
use crate::install;
#[derive(Parser)]
#[command(
name = "wayland-mouse",
version,
about = "Mac-like mouse acceleration for Wayland — pointer + scroll wheel."
)]
struct Cli {
#[command(subcommand)]
cmd: Option<Command>,
#[arg(long, global = true)]
debug: bool,
#[arg(long, global = true, value_name = "PATH")]
config: Option<PathBuf>,
}
#[derive(Subcommand)]
enum Command {
Run,
Install,
Uninstall,
Status,
Buttons,
#[cfg(feature = "tune")]
Tune,
Config {
#[arg(long)]
print: bool,
#[arg(long)]
check: bool,
},
}
pub fn main() {
let cli = Cli::parse();
let cfg_path = cli
.config
.clone()
.unwrap_or_else(|| PathBuf::from(config::CONFIG_PATH));
match cli.cmd {
None | Some(Command::Run) => run_daemon(cli.debug, &cfg_path),
Some(Command::Install) => std::process::exit(install::install()),
Some(Command::Uninstall) => std::process::exit(install::uninstall()),
Some(Command::Status) => std::process::exit(install::status()),
Some(Command::Buttons) => std::process::exit(device::watch_buttons()),
#[cfg(feature = "tune")]
Some(Command::Tune) => std::process::exit(crate::tune::run()),
Some(Command::Config { print: _, check }) => {
let code = if check {
config::check(&cfg_path)
} else {
config::print_effective(&cfg_path)
};
std::process::exit(code);
}
}
}
fn run_daemon(debug: bool, path: &std::path::Path) {
let mut cf = match config::load(path) {
Ok(c) => c,
Err(e) => {
eprintln!("wayland-mouse: config error: {e}");
eprintln!("wayland-mouse: falling back to built-in defaults");
config::ConfigFile::default()
}
};
if !path.exists() {
eprintln!(
"wayland-mouse: no {} — using built-in defaults (preset = mac-like)",
path.display()
);
}
if debug {
cf.debug = true;
}
let shared = crate::ipc::Shared::new(cf, path.to_path_buf());
device::run(shared); }