obsidian_logging/
template.rs1use crate::config::Config;
2use chrono::{Datelike, Duration, Local, Locale, Weekday};
3use std::fs::{self};
4use std::path::PathBuf;
5
6pub struct TemplateData {
7 pub today: String,
8 pub yesterday: String,
9 pub tomorrow: String,
10 pub weekday: String,
11 pub created: String,
12}
13
14impl TemplateData {
15 fn map_locale(locale_str: &str) -> Option<Locale> {
16 match locale_str {
17 "en_US" => Some(Locale::en_US),
18 "nb_NO" => Some(Locale::nb_NO), "nn_NO" => Some(Locale::nn_NO), "de_DE" => Some(Locale::de_DE), "fr_FR" => Some(Locale::fr_FR), "es_ES" => Some(Locale::es_ES), "it_IT" => Some(Locale::it_IT), "ja_JP" => Some(Locale::ja_JP), "ko_KR" => Some(Locale::ko_KR), "ru_RU" => Some(Locale::ru_RU), "zh_CN" => Some(Locale::zh_CN), _ => Some(Locale::nb_NO),
29 }
30 }
31
32 fn get_weekday_name(weekday: Weekday, locale: Locale) -> String {
33 let base_monday = chrono::NaiveDate::from_ymd_opt(2024, 1, 1).unwrap();
35 let days_to_add = match weekday {
36 Weekday::Mon => 0,
37 Weekday::Tue => 1,
38 Weekday::Wed => 2,
39 Weekday::Thu => 3,
40 Weekday::Fri => 4,
41 Weekday::Sat => 5,
42 Weekday::Sun => 6,
43 };
44 let target_date = base_monday + Duration::days(days_to_add);
45 target_date
46 .format_localized("%A", locale)
47 .to_string()
48 .to_lowercase()
49 }
50
51 pub fn new(locale_str: Option<&str>) -> Self {
52 let now = Local::now();
53 let today = now.date_naive();
54 let yesterday = today - Duration::days(1);
55 let tomorrow = today + Duration::days(1);
56
57 let weekday = match locale_str {
59 Some(loc) => match Self::map_locale(loc) {
60 Some(locale) => Self::get_weekday_name(today.weekday(), locale),
61 None => Self::weekday_to_string(today.weekday()),
62 },
63 None => Self::weekday_to_string(today.weekday()),
64 };
65
66 Self {
67 today: today.format("%Y-%m-%d").to_string(),
68 yesterday: yesterday.format("%Y-%m-%d").to_string(),
69 tomorrow: tomorrow.format("%Y-%m-%d").to_string(),
70 weekday,
71 created: now.format("%Y-%m-%d %H:%M:%S").to_string(),
72 }
73 }
74
75 fn weekday_to_string(weekday: Weekday) -> String {
77 match weekday {
78 Weekday::Mon => "monday",
79 Weekday::Tue => "tuesday",
80 Weekday::Wed => "wednesday",
81 Weekday::Thu => "thursday",
82 Weekday::Fri => "friday",
83 Weekday::Sat => "saturday",
84 Weekday::Sun => "sunday",
85 }
86 .to_string()
87 }
88}
89
90pub fn process_template(template_path: &str, data: &TemplateData) -> String {
91 let expanded_path = if template_path.starts_with("~") {
93 if let Ok(home) = std::env::var("HOME") {
94 let path = template_path.strip_prefix("~").unwrap_or(template_path);
95 PathBuf::from(home).join(path.strip_prefix("/").unwrap_or(path))
96 } else {
97 PathBuf::from(template_path)
98 }
99 } else {
100 PathBuf::from(template_path)
101 };
102
103 let template = match fs::read_to_string(&expanded_path) {
104 Ok(content) => content,
105 Err(_) => String::from("## 🕗\n\n"),
106 };
107
108 template
109 .replace("{today}", &data.today)
110 .replace("{yesterday}", &data.yesterday)
111 .replace("{tomorrow}", &data.tomorrow)
112 .replace("{weekday}", &data.weekday)
113 .replace("{created}", &data.created)
114}
115
116pub fn get_template_content(config: &Config) -> String {
117 let template_data = TemplateData::new(config.locale.as_deref());
118
119 match &config.template_path {
120 Some(path) => process_template(path, &template_data),
121 None => String::from("## 🕗\n\n"),
122 }
123}