summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLars Wirzenius <liw@liw.fi>2021-04-08 08:24:40 +0300
committerLars Wirzenius <liw@liw.fi>2021-04-08 09:37:21 +0300
commitfc917bf829c8a7cbf950754abc7085ffb00dbf17 (patch)
treedebaa476835926b80af97d47d4df6c7a72c2e0c7 /src
parent518e7dc2d5f97387702af0a300cc2842bd0deec6 (diff)
downloadjt2-fc917bf829c8a7cbf950754abc7085ffb00dbf17.tar.gz
feat! add support for tera templates for new journal entries
There is a hardcoded default template, plus one can be overridden per journal by adding a .config/templates/new_entry file in the journal.
Diffstat (limited to 'src')
-rw-r--r--src/error.rs8
-rw-r--r--src/journal.rs18
-rw-r--r--src/lib.rs1
-rw-r--r--src/template.rs45
4 files changed, 69 insertions, 3 deletions
diff --git a/src/error.rs b/src/error.rs
index 199d1e4..a6f239e 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -61,4 +61,12 @@ pub enum JournalError {
/// Editor failed.
#[error("editor {0} failed: {1}")]
EditorFailed(PathBuf, String),
+
+ /// Template not found.
+ #[error("template not found: {0}")]
+ TemplateNotFound(String),
+
+ /// Failed to render a Tera template.
+ #[error("template {0} failed to render: {1}")]
+ TemplateRender(String, #[source] tera::Error),
}
diff --git a/src/journal.rs b/src/journal.rs
index f58e49d..e5a692e 100644
--- a/src/journal.rs
+++ b/src/journal.rs
@@ -1,13 +1,16 @@
use crate::error::JournalError;
+use crate::template::Templates;
use chrono::Local;
use std::path::{Path, PathBuf};
use std::process::Command;
+use tera::Context;
const MAX_DRAFT_COUNT: usize = 1000;
pub struct Journal {
dirname: PathBuf,
entries: PathBuf,
+ templates: Templates,
}
impl Journal {
@@ -23,6 +26,7 @@ impl Journal {
Ok(Self {
dirname: path.to_path_buf(),
entries: entries.to_path_buf(),
+ templates: Templates::new(path)?,
})
}
@@ -30,7 +34,12 @@ impl Journal {
if Self::is_journal(path, entries) {
let dirname = path.to_path_buf();
let entries = entries.to_path_buf();
- Ok(Self { dirname, entries })
+ let templates = Templates::new(path)?;
+ Ok(Self {
+ dirname,
+ entries,
+ templates,
+ })
} else {
Err(JournalError::NotAJournal(path.display().to_string()))
}
@@ -55,9 +64,12 @@ impl Journal {
.map_err(|err| JournalError::CreateDirectory(drafts.to_path_buf(), err))?;
}
+ let mut context = Context::new();
+ context.insert("title", title);
+
let pathname = self.pick_file_id(&drafts)?;
- let text = format!(r#"[[!meta title="{}"]]"#, title);
- std::fs::write(&pathname, format!("{}\n\n", text))
+ let text = self.templates.new_draft(&context)?;
+ std::fs::write(&pathname, text)
.map_err(|err| JournalError::WriteEntry(pathname.to_path_buf(), err))?;
self.edit(editor, &pathname)?;
Ok(())
diff --git a/src/lib.rs b/src/lib.rs
index e988c12..d9b0801 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -2,3 +2,4 @@ pub mod config;
pub mod error;
pub mod journal;
pub mod opt;
+pub mod template;
diff --git a/src/template.rs b/src/template.rs
new file mode 100644
index 0000000..1ad8a54
--- /dev/null
+++ b/src/template.rs
@@ -0,0 +1,45 @@
+use crate::error::JournalError;
+use std::path::Path;
+use tera::{Context, Tera};
+
+const NEW_ENTRY: &str = r#"[[!meta title="{{ title }}"]]
+
+This is the default template.
+"#;
+
+pub struct Templates {
+ tera: Tera,
+}
+
+impl Templates {
+ pub fn new(dirname: &Path) -> Result<Self, JournalError> {
+ let glob = format!("{}/.config/templates/*", dirname.display());
+ let mut tera = Tera::new(&glob).expect("Tera::new");
+ add_default_template(&mut tera, "new_entry", NEW_ENTRY);
+ Ok(Self { tera })
+ }
+
+ pub fn new_draft(&self, context: &Context) -> Result<String, JournalError> {
+ self.render("new_entry", &context)
+ }
+
+ fn render(&self, name: &str, context: &Context) -> Result<String, JournalError> {
+ match self.tera.render(name, &context) {
+ Ok(s) => Ok(s),
+ Err(e) => match e.kind {
+ tera::ErrorKind::TemplateNotFound(x) => Err(JournalError::TemplateNotFound(x)),
+ _ => Err(JournalError::TemplateRender(name.to_string(), e)),
+ },
+ }
+ }
+}
+
+fn add_default_template(tera: &mut Tera, name: &str, template: &str) {
+ let context = Context::new();
+ if let Err(err) = tera.render(name, &context) {
+ if let tera::ErrorKind::TemplateNotFound(_) = err.kind {
+ tera.add_raw_template(name, template)
+ .expect("Tera::add_raw_template");
+ }
+ }
+}