1#![deny(
2 anonymous_parameters,
3 bare_trait_objects,
4 clippy::all,
5 clippy::complexity,
6 clippy::correctness,
7 clippy::nursery,
8 clippy::pedantic,
9 clippy::perf,
10 clippy::style,
11 elided_lifetimes_in_paths,
12 missing_copy_implementations,
13 missing_debug_implementations,
14 single_use_lifetimes,
15 trivial_casts,
16 trivial_numeric_casts,
17 unreachable_pub,
18 unsafe_code,
19 unused_import_braces,
20 unused_qualifications,
21 variant_size_differences
22)]
23#![allow(
24 clippy::missing_const_for_fn, clippy::missing_errors_doc,
26 clippy::non_ascii_literal,
27 clippy::redundant_pub_crate,
28 clippy::uninlined_format_args, clippy::unused_self,
30 clippy::use_self
31)]
32#![cfg_attr(all(test, feature = "mocking"), allow(trivial_casts, unsafe_code))]
33#![cfg_attr(all(test, feature = "mocking"), feature(proc_macro_hygiene))]
34
35use std::collections::HashSet;
36
37use crate::error::Error;
38use crate::error::Result;
39use crate::error::ResultExt;
40use crate::status_bar::StatusBar;
41use crate::wrapper::channel;
42use crate::wrapper::termination;
43
44#[macro_use]
45mod macros;
46mod communication;
47mod error;
48mod feature;
49mod features;
50mod resume;
51mod settings;
52mod status_bar;
53#[cfg(test)]
54mod test_utils;
55mod utils;
56mod wrapper;
57
58fn validate_settings(settings: &settings::Settings) -> Result<()> {
59 if settings.general.order.is_empty() {
60 return Err(Error::new_custom("settings", "no features enabled"));
61 }
62
63 let set: HashSet<&String> = settings.general.order.iter().collect();
64 if set.len() < settings.general.order.len() {
65 return Err(Error::new_custom(
66 "settings",
67 "order must not have more than one entry of one feature",
68 ));
69 }
70
71 Ok(())
72}
73
74pub fn run(config_path: &str) -> Result<()> {
75 let settings = settings::Settings::init(config_path)?;
76
77 validate_settings(&settings)?;
78
79 let (sender, receiver) = channel::create();
80 let mut features = Vec::new();
81
82 for (index, feature_name) in settings.general.order.iter().enumerate() {
83 let mut feature = features::create_feature(index, feature_name, &sender, &settings)?;
84 feature.init_notifier()?;
85 features.push(feature);
86 }
87
88 resume::init_resume_notifier(&sender)?;
89
90 sender.send(communication::Message::UpdateAll)?;
91
92 termination::register_handler(move || {
93 sender
94 .send(communication::Message::Kill)
95 .show_error_and_ignore();
96 })?;
97
98 let mut status_bar = StatusBar::init(features)?;
99
100 while let Ok(message) = receiver.read_blocking() {
101 match message {
102 communication::Message::Kill => break,
103 _ => status_bar.update(&message, &settings.general)?,
104 }
105 }
106
107 Ok(())
108}