digest: inline label_dates closures into DigestLevel definitions

Move weekly_label_dates and monthly_label_dates bodies into their
DigestLevel const definitions as closures, matching the style already
used by date_to_label. All per-level behavior is now co-located.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
ProofOfConcept 2026-03-03 18:06:59 -05:00 committed by Kent Overstreet
parent a9b90f881e
commit 152cd3ab63

View file

@ -42,6 +42,19 @@ const DAILY: DigestLevel = DigestLevel {
date_to_label: |date| Some(date.to_string()),
};
/// Week label and 7 dates (Mon-Sun) for the week containing `date`.
fn week_dates(date: &str) -> Result<(String, Vec<String>), String> {
let nd = NaiveDate::parse_from_str(date, "%Y-%m-%d")
.map_err(|e| format!("bad date '{}': {}", date, e))?;
let iso = nd.iso_week();
let week_label = format!("{}-W{:02}", iso.year(), iso.week());
let monday = nd - Duration::days(nd.weekday().num_days_from_monday() as i64);
let dates = (0..7)
.map(|i| (monday + Duration::days(i)).format("%Y-%m-%d").to_string())
.collect();
Ok((week_label, dates))
}
const WEEKLY: DigestLevel = DigestLevel {
name: "weekly",
title: "Weekly",
@ -49,7 +62,21 @@ const WEEKLY: DigestLevel = DigestLevel {
input_title: "Daily digests",
timeout: 300,
child_name: Some("daily"),
label_dates: weekly_label_dates,
label_dates: |arg| {
if !arg.contains('W') {
return week_dates(arg);
}
let (y, w) = arg.split_once("-W")
.ok_or_else(|| format!("bad week label: {}", arg))?;
let year: i32 = y.parse().map_err(|_| format!("bad week year: {}", arg))?;
let week: u32 = w.parse().map_err(|_| format!("bad week number: {}", arg))?;
let monday = NaiveDate::from_isoywd_opt(year, week, chrono::Weekday::Mon)
.ok_or_else(|| format!("invalid week: {}", arg))?;
let dates = (0..7)
.map(|i| (monday + Duration::days(i)).format("%Y-%m-%d").to_string())
.collect();
Ok((arg.to_string(), dates))
},
date_to_label: |date| week_dates(date).ok().map(|(l, _)| l),
};
@ -60,11 +87,32 @@ const MONTHLY: DigestLevel = DigestLevel {
input_title: "Weekly digests",
timeout: 600,
child_name: Some("weekly"),
label_dates: monthly_label_dates,
label_dates: |arg| {
let (year, month) = if arg.len() <= 7 {
let d = NaiveDate::parse_from_str(&format!("{}-01", arg), "%Y-%m-%d")
.map_err(|e| format!("bad month '{}': {}", arg, e))?;
(d.year(), d.month())
} else {
let d = NaiveDate::parse_from_str(arg, "%Y-%m-%d")
.map_err(|e| format!("bad date '{}': {}", arg, e))?;
(d.year(), d.month())
};
let label = format!("{}-{:02}", year, month);
let mut dates = Vec::new();
let mut day = 1u32;
while let Some(date) = NaiveDate::from_ymd_opt(year, month, day) {
if date.month() != month { break; }
dates.push(date.format("%Y-%m-%d").to_string());
day += 1;
}
Ok((label, dates))
},
date_to_label: |date| NaiveDate::parse_from_str(date, "%Y-%m-%d")
.ok().map(|d| format!("{}-{:02}", d.year(), d.month())),
};
const LEVELS: &[&DigestLevel] = &[&DAILY, &WEEKLY, &MONTHLY];
// --- Input gathering ---
/// Load child digest files from the episodic directory.
@ -202,65 +250,8 @@ pub fn generate(store: &mut Store, level_name: &str, arg: &str) -> Result<(), St
generate_digest(store, level, &label, &inputs)
}
// --- Date helpers ---
/// Week label and 7 dates (Mon-Sun) for the week containing `date`.
fn week_dates(date: &str) -> Result<(String, Vec<String>), String> {
let nd = NaiveDate::parse_from_str(date, "%Y-%m-%d")
.map_err(|e| format!("bad date '{}': {}", date, e))?;
let iso = nd.iso_week();
let week_label = format!("{}-W{:02}", iso.year(), iso.week());
let monday = nd - Duration::days(nd.weekday().num_days_from_monday() as i64);
let dates = (0..7)
.map(|i| (monday + Duration::days(i)).format("%Y-%m-%d").to_string())
.collect();
Ok((week_label, dates))
}
/// label_dates for weekly: accepts "YYYY-MM-DD" or "YYYY-WNN".
fn weekly_label_dates(arg: &str) -> Result<(String, Vec<String>), String> {
if !arg.contains('W') {
return week_dates(arg);
}
// Parse "YYYY-WNN"
let (y, w) = arg.split_once("-W")
.ok_or_else(|| format!("bad week label: {}", arg))?;
let year: i32 = y.parse().map_err(|_| format!("bad week year: {}", arg))?;
let week: u32 = w.parse().map_err(|_| format!("bad week number: {}", arg))?;
let monday = NaiveDate::from_isoywd_opt(year, week, chrono::Weekday::Mon)
.ok_or_else(|| format!("invalid week: {}", arg))?;
let dates = (0..7)
.map(|i| (monday + Duration::days(i)).format("%Y-%m-%d").to_string())
.collect();
Ok((arg.to_string(), dates))
}
/// label_dates for monthly: accepts "YYYY-MM" or "YYYY-MM-DD".
fn monthly_label_dates(arg: &str) -> Result<(String, Vec<String>), String> {
let (year, month) = if arg.len() <= 7 {
let d = NaiveDate::parse_from_str(&format!("{}-01", arg), "%Y-%m-%d")
.map_err(|e| format!("bad month '{}': {}", arg, e))?;
(d.year(), d.month())
} else {
let d = NaiveDate::parse_from_str(arg, "%Y-%m-%d")
.map_err(|e| format!("bad date '{}': {}", arg, e))?;
(d.year(), d.month())
};
let label = format!("{}-{:02}", year, month);
let mut dates = Vec::new();
let mut d = 1u32;
while let Some(date) = NaiveDate::from_ymd_opt(year, month, d) {
if date.month() != month { break; }
dates.push(date.format("%Y-%m-%d").to_string());
d += 1;
}
Ok((label, dates))
}
// --- Auto-detect and generate missing digests ---
const LEVELS: &[&DigestLevel] = &[&DAILY, &WEEKLY, &MONTHLY];
pub fn digest_auto(store: &mut Store) -> Result<(), String> {
let today = Local::now().format("%Y-%m-%d").to_string();
let epi = memory_subdir("episodic")?;
@ -308,7 +299,6 @@ pub fn digest_auto(store: &mut Store) -> Result<(), String> {
Ok(())
}
// --- Digest link parsing ---
// Replaces digest-link-parser.py: parses ## Links sections from digest
// files and applies them to the memory graph.