Skip to main content

harper_core/expr/
time_unit_expr.rs

1use crate::expr::LongestMatchOf;
2use crate::patterns::WordSet;
3use crate::{Span, Token};
4
5use super::Expr;
6
7/// Matches a time unit.
8///
9/// Matches standard units from microsecond to decade.
10/// Matches other 'units' such as moment, night, weekend.
11/// Matches singular and plural forms.
12/// Matches possessive forms (which are also common misspellings for the plurals).
13/// Matches abbreviations.
14#[derive(Default)]
15pub struct TimeUnitExpr {
16    include_plurals_only: bool,
17}
18
19impl TimeUnitExpr {
20    /// Creates a TimeUnitExpr that only matches plural time units
21    pub fn plurals_only() -> Self {
22        Self {
23            include_plurals_only: true,
24        }
25    }
26}
27
28impl Expr for TimeUnitExpr {
29    fn run(&self, cursor: usize, tokens: &[Token], source: &[char]) -> Option<Span<Token>> {
30        if tokens.is_empty() {
31            return None;
32        }
33
34        let units_definite_singular = WordSet::new(&[
35            "microsecond",
36            "millisecond",
37            "second",
38            "minute",
39            "hour",
40            "day",
41            "week",
42            "month",
43            "year",
44            "decade",
45        ]);
46
47        let units_definite_plural = WordSet::new(&[
48            "microseconds",
49            "milliseconds",
50            "seconds",
51            "minutes",
52            "hours",
53            "days",
54            "weeks",
55            "months",
56            "years",
57            "decades",
58        ]);
59
60        let units_definite_apos = WordSet::new(&[
61            "microsecond's",
62            "millisecond's",
63            "second's",
64            "minute's",
65            "hour's",
66            "day's",
67            "week's",
68            "month's",
69            "year's",
70            "decade's",
71        ]);
72
73        // ms
74        let units_definite_abbrev = WordSet::new(&["ms"]);
75
76        let units_other_singular = WordSet::new(&["moment", "night", "weekend"]);
77        let units_other_plural = WordSet::new(&["moments", "nights", "weekends"]);
78        let units_other_apos = WordSet::new(&["moment's", "night's", "weekend's"]);
79
80        let units = if self.include_plurals_only {
81            LongestMatchOf::new(vec![
82                Box::new(units_definite_plural),
83                Box::new(units_other_plural),
84            ])
85        } else {
86            LongestMatchOf::new(vec![
87                Box::new(units_definite_singular),
88                Box::new(units_definite_plural),
89                Box::new(units_other_singular),
90                Box::new(units_other_plural),
91                Box::new(units_definite_abbrev),
92                Box::new(units_definite_apos),
93                Box::new(units_other_apos),
94            ])
95        };
96
97        units.run(cursor, tokens, source)
98    }
99}