Krolyxon
Commit 92928dd

Branches

Tags

Refs →

remagesrcmain.rs

147 lines · 4.3 KB · Rust

1//! remage: a keyboard-centric image viewer.
2
3mod action;
4mod anim;
5mod app;
6mod cache;
7mod cli;
8mod config;
9mod decode;
10mod exec;
11mod input;
12mod ipc;
13mod render;
14mod scan;
15mod state;
16mod thumbs;
17mod ui;
18mod worker;
19
20use std::path::Path;
21use std::time::Instant;
22
23use clap::Parser;
24use winit::event_loop::EventLoop;
25
26use app::{App, Options, Overrides, UserEvent};
27use state::queue::Queue;
28use state::{AppState, MsgKind, Settings};
29
30fn main() -> anyhow::Result<()> {
31 let started = Instant::now();
32 env_logger::init();
33 let cli = cli::Cli::parse();
34 if cli.dump_config {
35 print!("{}", config::dump());
36 return Ok(());
37 }
38 if cli.check_config {
39 check_config(cli.config.as_deref());
40 }
41 log::info!("remage {}", env!("CARGO_PKG_VERSION"));
42
43 let (loaded, config_error) = match config::load(cli.config.as_deref()) {
44 Ok(l) => (l, None),
45 Err(e) => {
46 log::error!("{e}");
47 let mut d = config::defaults();
48 d.watch = e.watch;
49 (d, Some(e.message))
50 }
51 };
52 for w in &loaded.warnings {
53 log::warn!("{w}");
54 }
55 log::debug!("config loaded after {:.1?}", started.elapsed());
56 let cfg = &loaded.config;
57
58 let scan = scan::scan(
59 &cli.paths,
60 &scan::ScanOptions {
61 recursive: cli.recursive || cfg.general.recursive,
62 siblings: !cli.no_siblings && cfg.general.open_siblings,
63 sort: cli.sort.unwrap_or(cfg.general.sort),
64 reverse: cli.reverse || cfg.general.reverse,
65 },
66 );
67 log::debug!(
68 "scanned {} files ({} to sniff) in {:.1?}",
69 scan.files.len(),
70 scan.unknown.len(),
71 started.elapsed()
72 );
73
74 let overrides = Overrides {
75 fit: cli.fit,
76 zoom: cli.zoom.map(|z| z / 100.0),
77 bar: cli.no_bar.then_some(false),
78 };
79 let mut settings = Settings::from_config(cfg);
80 overrides.apply(&mut settings);
81 let start_index = cli.start.unwrap_or(1).saturating_sub(1);
82 let queue = Queue::new(scan.files, scan.start.as_deref(), start_index);
83 let bar = overrides.bar.unwrap_or(cfg.ui.statusbar);
84 let mut state = AppState::new(queue, settings, bar, Instant::now());
85 state.theme = loaded.theme.clone();
86 state.nearest = cfg.image.filter.nearest();
87 state.alpha_bg = cfg.image.alpha_background;
88 if let Some(err) = scan.errors.first() {
89 state.notify(format!("error: {err}"), MsgKind::Error, Instant::now());
90 }
91
92 let event_loop = EventLoop::<UserEvent>::with_user_event().build()?;
93 let proxy = event_loop.create_proxy();
94 if !scan.unknown.is_empty() {
95 let proxy = proxy.clone();
96 let unknown = scan.unknown;
97 std::thread::spawn(move || {
98 let found: Vec<_> = unknown.into_iter().filter(|p| decode::sniff(p)).collect();
99 if !found.is_empty() {
100 let _ = proxy.send_event(UserEvent::Found(found));
101 }
102 });
103 }
104 let watch = {
105 let proxy = proxy.clone();
106 config::watch::spawn(cli.config.clone(), loaded.watch.clone(), move |r| {
107 let _ = proxy.send_event(UserEvent::Config(Box::new(r)));
108 })
109 };
110
111 let opts = Options {
112 fullscreen: cli.fullscreen || cfg.window.fullscreen,
113 geometry: cli.geometry,
114 class: cli.class.unwrap_or_else(|| cfg.window.class.clone()),
115 overrides,
116 };
117 let mut app = App::new(opts, state, proxy, loaded, watch);
118 if let Some(e) = config_error {
119 app.config_failed(&e);
120 }
121 event_loop.run_app(&mut app)?;
122 match app.error.take() {
123 Some(e) => Err(e),
124 None => Ok(()),
125 }
126}
127
128/// `--check-config`: report and exit, non-zero on errors.
129fn check_config(path: Option<&Path>) -> ! {
130 match config::load(path) {
131 Ok(l) => {
132 for w in &l.warnings {
133 eprintln!("warning: {w}");
134 }
135 match path.map(Path::to_path_buf).or_else(config::default_path) {
136 Some(p) if p.is_file() => println!("{}: ok", p.display()),
137 Some(p) => println!("{} not found: using the defaults", p.display()),
138 None => println!("no config directory: using the defaults"),
139 }
140 std::process::exit(0)
141 }
142 Err(e) => {
143 eprintln!("{e}");
144 std::process::exit(1)
145 }
146 }
147}