summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Silverstone <dsilvers+gitlab@digital-scurf.org>2021-04-08 09:03:50 +0000
committerDaniel Silverstone <dsilvers+gitlab@digital-scurf.org>2021-04-08 09:03:50 +0000
commit924fc1add2de3edac4ad4b1097a3bbbb73d0ad50 (patch)
treee5c9689e1ff60953502faf55eacb8a82c2726b8a
parent518e7dc2d5f97387702af0a300cc2842bd0deec6 (diff)
parent0b0cc421e79bff9f8692e8c771c5e72ee4414032 (diff)
downloadjt2-924fc1add2de3edac4ad4b1097a3bbbb73d0ad50.tar.gz
Merge branch 'tera' into 'main'
feat! add support for tera templates for new journal entries Closes #8 and #10 See merge request larswirzenius/jt!11
-rw-r--r--Cargo.lock298
-rw-r--r--Cargo.toml13
-rw-r--r--jt.md23
-rw-r--r--src/error.rs8
-rw-r--r--src/journal.rs27
-rw-r--r--src/lib.rs1
-rw-r--r--src/template.rs46
7 files changed, 396 insertions, 20 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 035e089..e6a7e11 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -20,9 +20,9 @@ dependencies = [
[[package]]
name = "anyhow"
-version = "1.0.39"
+version = "1.0.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "81cddc5f91628367664cc7c69714ff08deee8a3efc54623011c772544d7b2767"
+checksum = "28b2cd92db5cbd74e8e5028f7e27dd7aa3090e89e4f2a197cc7c8dfb69c7063b"
[[package]]
name = "atty"
@@ -48,6 +48,48 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
[[package]]
+name = "block-buffer"
+version = "0.7.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b"
+dependencies = [
+ "block-padding",
+ "byte-tools",
+ "byteorder",
+ "generic-array",
+]
+
+[[package]]
+name = "block-padding"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5"
+dependencies = [
+ "byte-tools",
+]
+
+[[package]]
+name = "bstr"
+version = "0.2.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a40b47ad93e1a5404e6c18dec46b628214fee441c70f4ab5d6942142cc268a3d"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "byte-tools"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7"
+
+[[package]]
+name = "byteorder"
+version = "1.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
+
+[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -82,6 +124,26 @@ dependencies = [
]
[[package]]
+name = "crossbeam-utils"
+version = "0.8.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e7e9d99fa91428effe99c5c6d4634cdeba32b8cf784fc428a2a687f61a952c49"
+dependencies = [
+ "autocfg",
+ "cfg-if",
+ "lazy_static",
+]
+
+[[package]]
+name = "digest"
+version = "0.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5"
+dependencies = [
+ "generic-array",
+]
+
+[[package]]
name = "directories-next"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -104,9 +166,9 @@ dependencies = [
[[package]]
name = "dtoa"
-version = "0.4.7"
+version = "0.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "88d7ed2934d741c6b37e33e3832298e8850b53fd2d2bea03873375596c7cea4e"
+checksum = "56899898ce76aaf4a0f24d914c97ea6ed976d42fec6ad33fcbb0a1103e07b2b0"
[[package]]
name = "env_logger"
@@ -122,6 +184,27 @@ dependencies = [
]
[[package]]
+name = "fake-simd"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
+
+[[package]]
+name = "fnv"
+version = "1.0.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
+
+[[package]]
+name = "generic-array"
+version = "0.12.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd"
+dependencies = [
+ "typenum",
+]
+
+[[package]]
name = "getrandom"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -133,6 +216,30 @@ dependencies = [
]
[[package]]
+name = "globset"
+version = "0.4.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c152169ef1e421390738366d2f796655fec62621dabbd0fd476f905934061e4a"
+dependencies = [
+ "aho-corasick",
+ "bstr",
+ "fnv",
+ "log",
+ "regex",
+]
+
+[[package]]
+name = "globwalk"
+version = "0.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "93e3af942408868f6934a7b85134a3230832b9977cf66125df2f9edcfce4ddcc"
+dependencies = [
+ "bitflags",
+ "ignore",
+ "walkdir",
+]
+
+[[package]]
name = "heck"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -160,6 +267,30 @@ dependencies = [
]
[[package]]
+name = "ignore"
+version = "0.4.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b287fb45c60bb826a0dc68ff08742b9d88a2fea13d6e0c286b3172065aaf878c"
+dependencies = [
+ "crossbeam-utils",
+ "globset",
+ "lazy_static",
+ "log",
+ "memchr",
+ "regex",
+ "same-file",
+ "thread_local",
+ "walkdir",
+ "winapi-util",
+]
+
+[[package]]
+name = "itoa"
+version = "0.4.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736"
+
+[[package]]
name = "jt2"
version = "0.1.0"
dependencies = [
@@ -172,6 +303,7 @@ dependencies = [
"serde",
"serde_yaml",
"structopt",
+ "tera",
"thiserror",
]
@@ -183,9 +315,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
-version = "0.2.91"
+version = "0.2.93"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8916b1f6ca17130ec6568feccee27c156ad12037880833a3b842a823236502e7"
+checksum = "9385f66bf6105b241aa65a61cb923ef20efc665cb9f9bb50ac2f0c4b7f378d41"
[[package]]
name = "linked-hash-map"
@@ -203,6 +335,12 @@ dependencies = [
]
[[package]]
+name = "maplit"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d"
+
+[[package]]
name = "memchr"
version = "2.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -228,6 +366,61 @@ dependencies = [
]
[[package]]
+name = "once_cell"
+version = "1.7.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "af8b08b04175473088b46763e51ee54da5f9a164bc162f615b91bc179dbf15a3"
+
+[[package]]
+name = "opaque-debug"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c"
+
+[[package]]
+name = "pest"
+version = "2.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53"
+dependencies = [
+ "ucd-trie",
+]
+
+[[package]]
+name = "pest_derive"
+version = "2.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "833d1ae558dc601e9a60366421196a8d94bc0ac980476d0b67e1d0988d72b2d0"
+dependencies = [
+ "pest",
+ "pest_generator",
+]
+
+[[package]]
+name = "pest_generator"
+version = "2.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "99b8db626e31e5b81787b9783425769681b347011cc59471e33ea46d2ea0cf55"
+dependencies = [
+ "pest",
+ "pest_meta",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "pest_meta"
+version = "2.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "54be6e404f5317079812fc8f9f5279de376d8856929e21c184ecf6bbd692a11d"
+dependencies = [
+ "maplit",
+ "pest",
+ "sha-1",
+]
+
+[[package]]
name = "pretty_env_logger"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -263,9 +456,9 @@ dependencies = [
[[package]]
name = "proc-macro2"
-version = "1.0.24"
+version = "1.0.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71"
+checksum = "a152013215dca273577e18d2bf00fa862b89b24169fb78c4c95aeb07992c9cec"
dependencies = [
"unicode-xid",
]
@@ -322,6 +515,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24d5f089152e60f62d28b835fbff2cd2e8dc0baf1ac13343bef92ab7eed84548"
[[package]]
+name = "ryu"
+version = "1.0.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
+
+[[package]]
+name = "same-file"
+version = "1.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
+dependencies = [
+ "winapi-util",
+]
+
+[[package]]
name = "serde"
version = "1.0.125"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -342,6 +550,17 @@ dependencies = [
]
[[package]]
+name = "serde_json"
+version = "1.0.64"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "799e97dc9fdae36a5c8b8f2cae9ce2ee9fdce2058c57a93e6099d919fd982f79"
+dependencies = [
+ "itoa",
+ "ryu",
+ "serde",
+]
+
+[[package]]
name = "serde_yaml"
version = "0.8.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -354,6 +573,18 @@ dependencies = [
]
[[package]]
+name = "sha-1"
+version = "0.8.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df"
+dependencies = [
+ "block-buffer",
+ "digest",
+ "fake-simd",
+ "opaque-debug",
+]
+
+[[package]]
name = "strsim"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -385,9 +616,9 @@ dependencies = [
[[package]]
name = "syn"
-version = "1.0.64"
+version = "1.0.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3fd9d1e9976102a03c542daa2eff1b43f9d72306342f3f8b3ed5fb8908195d6f"
+checksum = "48fe99c6bd8b1cc636890bcc071842de909d902c81ac7dab53ba33c421ab8ffb"
dependencies = [
"proc-macro2",
"quote",
@@ -395,6 +626,21 @@ dependencies = [
]
[[package]]
+name = "tera"
+version = "1.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5cb278a72e426f291faf182cb0e0cb7d20241e8e9881046724ac874a83c62346"
+dependencies = [
+ "globwalk",
+ "lazy_static",
+ "pest",
+ "pest_derive",
+ "regex",
+ "serde",
+ "serde_json",
+]
+
+[[package]]
name = "termcolor"
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -433,6 +679,15 @@ dependencies = [
]
[[package]]
+name = "thread_local"
+version = "1.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8018d24e04c95ac8790716a5987d0fec4f8b27249ffa0f7d33f1369bdfb88cbd"
+dependencies = [
+ "once_cell",
+]
+
+[[package]]
name = "time"
version = "0.1.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -443,6 +698,18 @@ dependencies = [
]
[[package]]
+name = "typenum"
+version = "1.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "879f6906492a7cd215bfa4cf595b600146ccfac0c79bcbd1f3000162af5e8b06"
+
+[[package]]
+name = "ucd-trie"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c"
+
+[[package]]
name = "unicode-segmentation"
version = "1.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -473,6 +740,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe"
[[package]]
+name = "walkdir"
+version = "2.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56"
+dependencies = [
+ "same-file",
+ "winapi",
+ "winapi-util",
+]
+
+[[package]]
name = "wasi"
version = "0.10.2+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/Cargo.toml b/Cargo.toml
index a76755a..6bbe649 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -5,13 +5,14 @@ authors = ["Lars Wirzenius <liw@liw.fi>"]
edition = "2018"
[dependencies]
-structopt = "0.3"
anyhow = "1"
-thiserror = "1"
-pretty_env_logger = "0.4"
-log = "0.4"
+chrono = "0.4"
directories-next = "2.0.0"
+log = "0.4"
+pretty_env_logger = "0.4"
+regex = "1"
serde = { version = "1", features = ["derive"] }
serde_yaml = "0.8"
-regex = "1"
-chrono = "0.4"
+structopt = "0.3"
+tera = { version = "1", default-features = false }
+thiserror = "1"
diff --git a/jt.md b/jt.md
index 9ee4d1d..d1f3b14 100644
--- a/jt.md
+++ b/jt.md
@@ -155,6 +155,7 @@ when I run jt2 --editor=none --dirname=jrnl new "Abracadabra"
then command is successful
and there is one draft in jrnl
and draft 0 in jrnl contains "Abracadabra"
+and draft 0 in jrnl contains "!meta date="
given an executable script append.sh
when I run jt2 --editor=./append.sh --dirname=jrnl edit 0
@@ -224,6 +225,28 @@ then there are no drafts in jrnl
+## Override template for new journal entries
+
+Verify that we can have a custom template for new journal entries.
+
+~~~scenario
+given an installed jt
+
+when I run jt2 --dirname jrnl init default "My test journal"
+then command is successful
+
+given file jrnl/.config/templates/new_entry from new_entry_template
+
+when I run jt2 --editor=none --dirname=jrnl new "Abracadabra"
+then command is successful
+and there is one draft in jrnl
+and draft 0 in jrnl contains "custom new entry template"
+~~~
+
+~~~{#new_entry_template .file .numberLines}
+This is a custom new entry template.
+~~~
+
# Colophon
This document is meant to be processed with the [Subplot][] program to
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..788a34b 100644
--- a/src/journal.rs
+++ b/src/journal.rs
@@ -1,13 +1,16 @@
use crate::error::JournalError;
-use chrono::Local;
+use crate::template::Templates;
+use chrono::{DateTime, 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,13 @@ impl Journal {
.map_err(|err| JournalError::CreateDirectory(drafts.to_path_buf(), err))?;
}
+ let mut context = Context::new();
+ context.insert("title", title);
+ context.insert("date", &current_timestamp());
+
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(())
@@ -139,3 +152,9 @@ fn is_dir(path: &Path) -> bool {
false
}
}
+
+fn current_timestamp() -> String {
+ let now = Local::now();
+ let now: DateTime<Local> = DateTime::from(now);
+ now.to_rfc2822()
+}
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..89c1a15
--- /dev/null
+++ b/src/template.rs
@@ -0,0 +1,46 @@
+use crate::error::JournalError;
+use std::path::Path;
+use tera::{Context, Tera};
+
+const NEW_ENTRY: &str = r#"[[!meta title="{{ title }}"]]
+[[!meta date="{{ date }}"]]
+
+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");
+ }
+ }
+}