mps-rs 1.7.0

MPS — plain-text personal productivity CLI (Rust)
Documentation
use regex::Regex;
use std::sync::OnceLock;

pub const MPS_EXT: &str = "mps";

// AT_REGEXP: matches @sign[args]{ or @sign{  (brackets optional)
// Group names: element_sign, args
pub fn at_regexp() -> &'static Regex {
    static RE: OnceLock<Regex> = OnceLock::new();
    RE.get_or_init(|| {
        Regex::new(r"@(?P<element_sign>[a-zA-Z0-9_]+)(?:\[(?P<args>[^\]]*)\])?\s*\{").unwrap()
    })
}

// END_CURLY_REGEXP: matches }
// Ruby used look-around to exclude '}'  but Rust regex doesn't support look-around.
// In practice MPS body text never contains single-quoted braces, so a plain } match is correct.
pub fn end_curly_regexp() -> &'static Regex {
    static RE: OnceLock<Regex> = OnceLock::new();
    RE.get_or_init(|| Regex::new(r"\}").unwrap())
}

// MPS_FILE_NAME_REGEXP: YYYYMMDD[.epoch].mps
pub fn mps_file_name_regexp() -> &'static Regex {
    static RE: OnceLock<Regex> = OnceLock::new();
    RE.get_or_init(|| {
        Regex::new(r"^(?P<datestamp>(?P<year>\d{4})(?P<month>\d{2})(?P<day>\d{2})(?:\.(?P<epoch>\d{10,}))?)\.mps$").unwrap()
    })
}

#[allow(dead_code)]
/// Returns "YYYYMMDD" prefix from a valid .mps filename, or None.
pub fn clip_date_from_filename(basename: &str) -> Option<&str> {
    let re = mps_file_name_regexp();
    re.find(basename).map(|_| &basename[..8])
}

/// Generate a new .mps filename for the given date using current unix epoch.
pub fn new_file_name(date: chrono::NaiveDate) -> String {
    let epoch = std::time::SystemTime::now()
        .duration_since(std::time::UNIX_EPOCH)
        .unwrap_or_default()
        .as_secs();
    format!("{}.{}.{}", date.format("%Y%m%d"), epoch, MPS_EXT)
}