lattice_notify/options.rs
1//! NOTIF.1e: the notification subsystem's typed options.
2//!
3//! Owned here rather than in `lattice-config` for the reason
4//! `lattice-diff`'s are — the subsystem owns its full surface, options
5//! included. Self-register via `linkme`; the host's
6//! `init_from_linkme()` walks the global slice at boot.
7
8/// Validator for `notifications.max-visible`. `0` is meaningful — it
9/// silences the corner entirely without unregistering the subsystem, so
10/// `*messages*` still records everything. The ceiling stops a value
11/// that would paper over the whole editor.
12#[allow(clippy::ptr_arg)]
13fn validate_max_visible(n: &i64) -> Result<(), String> {
14 if *n >= 0 && *n <= 20 {
15 Ok(())
16 } else {
17 Err(format!(
18 "notifications.max-visible must be in range [0, 20], got {n}"
19 ))
20 }
21}
22
23/// Validator for `notifications.timeout`. Must be positive: `0` would
24/// mean a notification that expires before it can be read, which is
25/// indistinguishable from the invisible-completion bug the subsystem
26/// exists to remove. Use `max-visible = 0` to silence the corner.
27#[allow(clippy::ptr_arg)]
28fn validate_timeout(n: &i64) -> Result<(), String> {
29 if *n >= 1 && *n <= 3600 {
30 Ok(())
31 } else {
32 Err(format!(
33 "notifications.timeout must be in range [1, 3600] seconds, got {n} \
34 (use `notifications.max-visible = 0` to show none)"
35 ))
36 }
37}
38
39lattice_config::options! {
40 group = lattice_config::Notifications;
41
42 /// How many notifications the corner shows at once. The rest queue,
43 /// and the stack shows `+N more`.
44 ///
45 /// `0` shows none — the subsystem keeps running and `*messages*`
46 /// keeps its record, so nothing is lost, it is just silent.
47 #[name("notifications.max-visible")]
48 #[validate(validate_max_visible)]
49 pub NotificationsMaxVisible: i64 = 3;
50
51 /// Seconds an **info** notification stays up.
52 ///
53 /// Warnings last twice this and errors four times it, and that
54 /// ratio is deliberate rather than three separate knobs: an error
55 /// you blink past is an error you will hit again, so raising this
56 /// must not leave errors relatively shorter than the successes
57 /// around them. One number keeps them ordered by construction.
58 #[name("notifications.timeout")]
59 #[validate(validate_timeout)]
60 pub NotificationsTimeout: i64 = 4;
61
62 /// Which corner the stack anchors to.
63 #[name("notifications.corner")]
64 pub NotificationsCorner: String = "bottom-right".to_string();
65}