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