diff options
author | Daniel Silverstone <dsilvers+gitlab@digital-scurf.org> | 2021-04-08 09:03:50 +0000 |
---|---|---|
committer | Daniel Silverstone <dsilvers+gitlab@digital-scurf.org> | 2021-04-08 09:03:50 +0000 |
commit | 924fc1add2de3edac4ad4b1097a3bbbb73d0ad50 (patch) | |
tree | e5c9689e1ff60953502faf55eacb8a82c2726b8a | |
parent | 518e7dc2d5f97387702af0a300cc2842bd0deec6 (diff) | |
parent | 0b0cc421e79bff9f8692e8c771c5e72ee4414032 (diff) | |
download | jt2-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.lock | 298 | ||||
-rw-r--r-- | Cargo.toml | 13 | ||||
-rw-r--r-- | jt.md | 23 | ||||
-rw-r--r-- | src/error.rs | 8 | ||||
-rw-r--r-- | src/journal.rs | 27 | ||||
-rw-r--r-- | src/lib.rs | 1 | ||||
-rw-r--r-- | src/template.rs | 46 |
7 files changed, 396 insertions, 20 deletions
@@ -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" @@ -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" @@ -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", ¤t_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() +} @@ -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"); + } + } +} |