dwm_status/
lib.rs

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, // seems to produce false positives
25    clippy::missing_errors_doc,
26    clippy::non_ascii_literal,
27    clippy::redundant_pub_crate,
28    clippy::uninlined_format_args, // until 1.65.0 is minimum version
29    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}