mod i18n;
mod icons;
mod shell;
mod theme;
mod ui;
mod wl;
use clap::Parser;
use std::sync::{Arc, Mutex, mpsc};
use ui::Mode;
#[derive(Parser)]
#[command(name = "wlr-chooser", version, about)]
struct Cli {
#[arg(short = 'w', long, group = "what")]
windows: bool,
#[arg(short = 'o', long, visible_alias = "screens", group = "what")]
outputs: bool,
#[arg(long, group = "what")]
both: bool,
#[arg(long)]
include_system: bool,
#[arg(long, value_name = "COLSxROWS", value_parser = parse_grid)]
grid: Option<(u32, u32)>,
}
fn parse_grid(s: &str) -> Result<(u32, u32), String> {
let (c, r) = s
.split_once(['x', 'X', '×'])
.ok_or("expected COLSxROWS, e.g. 4x3")?;
let n = |v: &str, what: &str| {
v.trim()
.parse::<u32>()
.ok()
.filter(|&n| n >= 1)
.ok_or(format!("{what} must be a positive integer"))
};
Ok((n(c, "columns")?, n(r, "rows")?))
}
fn main() {
let cli = Cli::parse();
i18n::init();
let mode = if cli.windows {
Mode::Windows
} else if cli.outputs {
Mode::Outputs
} else {
Mode::All
};
let (tx, rx) = mpsc::channel();
std::thread::spawn(move || ui::capture_thread(tx));
let out: ui::Outcome = Arc::new(Mutex::new(None));
let out_for_app = out.clone();
let theme = theme::Theme::load();
let app = ui::App::new(rx, out_for_app, mode, cli.include_system, cli.grid, theme);
if let Err(e) = shell::run(app) {
eprintln!("{}", tr!("error", error = format!("{e:#}")));
std::process::exit(2);
}
match out.lock().unwrap().take() {
Some(token) => {
println!("{token}");
std::process::exit(0);
}
None => std::process::exit(1), }
}