texlang_stdlib/
time.rs

1//! Time commands (`\year`, `\month`, etc.)
2
3#[cfg(feature = "time")]
4use chrono::prelude::*;
5use texlang::{command, variable, vm::HasComponent};
6
7/// Component for storing state related to the time commands.
8#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
9pub struct Component {
10    minutes_since_midnight: i32,
11    day: i32,
12    month: i32,
13    year: i32,
14}
15
16impl Component {
17    /// Create a new component with the variables initialized to the current time.
18    #[cfg(feature = "time")]
19    pub fn new() -> Component {
20        let dt: DateTime<Local> = Local::now();
21        Component {
22            minutes_since_midnight: 60 * (dt.time().hour() as i32) + (dt.time().minute() as i32),
23            day: dt.day() as i32,
24            month: dt.month() as i32,
25            year: dt.year(),
26        }
27    }
28
29    #[cfg(not(feature = "time"))]
30    pub fn new() -> Component {
31        Component {
32            minutes_since_midnight: 0,
33            day: 0,
34            month: 0,
35            year: 0,
36        }
37    }
38
39    /// Create a new component with the variable initialized with the provided values.
40    ///
41    /// This is useful in situations where the DateTime library can't be used; e.g., when
42    /// Texcraft is compiled to WebAssembly and running in the browser.
43    pub fn new_with_values(
44        minutes_since_midnight: i32,
45        day: i32,
46        month: i32,
47        year: i32,
48    ) -> Component {
49        Component {
50            minutes_since_midnight,
51            day,
52            month,
53            year,
54        }
55    }
56}
57
58impl Default for Component {
59    fn default() -> Self {
60        Self::new()
61    }
62}
63
64/// Get the `\time` command.
65pub fn get_time<S: HasComponent<Component>>() -> command::BuiltIn<S> {
66    variable::Command::new_singleton(
67        |state: &S, _: variable::Index| -> &i32 { &state.component().minutes_since_midnight },
68        |state: &mut S, _: variable::Index| -> &mut i32 {
69            &mut state.component_mut().minutes_since_midnight
70        },
71    )
72    .into()
73}
74
75/// Get the `\day` command.
76pub fn get_day<S: HasComponent<Component>>() -> command::BuiltIn<S> {
77    variable::Command::new_singleton(
78        |state: &S, _: variable::Index| -> &i32 { &state.component().day },
79        |state: &mut S, _: variable::Index| -> &mut i32 { &mut state.component_mut().day },
80    )
81    .into()
82}
83
84/// Get the `\month` command.
85pub fn get_month<S: HasComponent<Component>>() -> command::BuiltIn<S> {
86    variable::Command::new_singleton(
87        |state: &S, _: variable::Index| -> &i32 { &state.component().month },
88        |state: &mut S, _: variable::Index| -> &mut i32 { &mut state.component_mut().month },
89    )
90    .into()
91}
92
93/// Get the `\year` command.
94pub fn get_year<S: HasComponent<Component>>() -> command::BuiltIn<S> {
95    variable::Command::new_singleton(
96        |state: &S, _: variable::Index| -> &i32 { &state.component().year },
97        |state: &mut S, _: variable::Index| -> &mut i32 { &mut state.component_mut().year },
98    )
99    .into()
100}