seam

Symbolic-Expressions As Markup.
git clone git://git.knutsen.co/seam
Log | Files | Refs | README | LICENSE

commit a1a5c7bfc09ccbee649a091b64ebed421b51bd86
parent b502afe1aa85eebb42acb4421de95c1713ab5e19
Author: Demonstrandum <moi@knutsen.co>
Date:   Sat, 10 Oct 2020 19:56:05 +0100

Added (%date "...") macro.

Diffstat:
MCargo.lock | 58+++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
MCargo.toml | 1+
MREADME.md | 1+
Asamples/blog-concept/blog/Entry 1.sex | 13+++++++++++++
Asamples/blog-concept/blog/Entry 2.sex | 13+++++++++++++
Asamples/blog-concept/blog/includes/footer.sex | 2++
Asamples/blog-concept/blog/includes/head.sex | 4++++
Asamples/blog-concept/blog/includes/header.sex | 2++
Asamples/blog-concept/blog/includes/style.sex | 8++++++++
Asamples/blog-concept/index.sex | 13+++++++++++++
Msrc/parse/expander.rs | 23+++++++++++++++++++++++
11 files changed, 137 insertions(+), 1 deletion(-)

diff --git a/Cargo.lock b/Cargo.lock @@ -12,6 +12,25 @@ dependencies = [ ] [[package]] +name = "autocfg" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" + +[[package]] +name = "chrono" +version = "0.4.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" +dependencies = [ + "libc", + "num-integer", + "num-traits", + "time", + "winapi", +] + +[[package]] name = "colored" version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -44,13 +63,50 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9457b06509d27052635f90d6466700c65095fdf75409b3fbdd903e988b886f49" [[package]] +name = "num-integer" +version = "0.1.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d59457e662d541ba17869cf51cf177c0b5f0cbf476c66bdc90bf1edac4f875b" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac267bcc07f48ee5f8935ab0d24f316fb722d7a1292e2913f0cc196b29ffd611" +dependencies = [ + "autocfg", +] + +[[package]] name = "seam" -version = "0.1.0" +version = "0.1.1" dependencies = [ + "chrono", "colored", ] [[package]] +name = "time" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" +dependencies = [ + "libc", + "wasi", + "winapi", +] + +[[package]] +name = "wasi" +version = "0.10.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" + +[[package]] name = "winapi" version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" diff --git a/Cargo.toml b/Cargo.toml @@ -19,3 +19,4 @@ path = "src/bin.rs" [dependencies] colored = "1.8" +chrono = "0.4" diff --git a/README.md b/README.md @@ -22,6 +22,7 @@ client. - CSS ## TODO + - Caching or checking time-stamps as to not regenerate unmodified source files. - HTML object `style="..."` object should handle s-expressions well, (e.g. `(p :style (:color red :border none) Hello World)`) - HTML `<style>` tag should allow for *normal* CSS syntax if just given a string. - Allow for, and handle special `@` syntax in CSS, such as `@import` and `@media`. diff --git a/samples/blog-concept/blog/Entry 1.sex b/samples/blog-concept/blog/Entry 1.sex @@ -0,0 +1,13 @@ +(%define title "My Blog Entry No. 1") + +(head + (title %title) + (%include "./includes/head.sex")) +(body + (%include "./includes/header.sex") + (h1 %title) + (p Hello, World!) + (p + Some content goes here...) + + (%include "./includes/footer.sex")) diff --git a/samples/blog-concept/blog/Entry 2.sex b/samples/blog-concept/blog/Entry 2.sex @@ -0,0 +1,13 @@ +(%define title "My Blog Entry No. 2") + +(head + (title %title) + (%include "./includes/head.sex")) +(body + (%include "./includes/header.sex") + (h1 %title) + (p Hello, Again!) + (p + Some more content goes here...) + + (%include "./includes/footer.sex")) diff --git a/samples/blog-concept/blog/includes/footer.sex b/samples/blog-concept/blog/includes/footer.sex @@ -0,0 +1,2 @@ +(br) +(a :href "/" Return Home) diff --git a/samples/blog-concept/blog/includes/head.sex b/samples/blog-concept/blog/includes/head.sex @@ -0,0 +1,4 @@ +(meta :name copyright :content "No, it's copyleft.") +(meta :name description :conetent "A blog page.") +(style (%include "./style.sex")) +(meta :name keywords :content "blog,personal,concept,information") diff --git a/samples/blog-concept/blog/includes/header.sex b/samples/blog-concept/blog/includes/header.sex @@ -0,0 +1,2 @@ +(center (h1 This is a Blog Webiste)) +;; Put some nav-bar or something here... diff --git a/samples/blog-concept/blog/includes/style.sex b/samples/blog-concept/blog/includes/style.sex @@ -0,0 +1,8 @@ +(body , html + :padding 0 + :margin 0) + +(body + :width 100% + :min-height 100% + :font-family sans-serif) diff --git a/samples/blog-concept/index.sex b/samples/blog-concept/index.sex @@ -0,0 +1,13 @@ +(!DOCTYPE html) +(html :lang en + (head + (title Blog Concept)) + (body + (h1 My Blog) + (h2 Index) + (%define blog-dir (%sort :by date (%dir "./blog/*.sex"))) + (ul + (%for file in %blog-dir + (%let ((short-title (%basename %file))) + (li (a :href (%concat "./blog"%short-title".html") %short-title))))) + (p What interests you?))) diff --git a/src/parse/expander.rs b/src/parse/expander.rs @@ -88,6 +88,29 @@ impl ExpansionContext { } Ok(expanded_tree) }, + "date" => { + let date_format = if let [ p ] = params.as_slice() { + p + } else { + return Err(ExpansionError::new( + &format!("`{}' macro only expects one formatting argument.", + name), + site)) + }; + + let (date_format, site) = if let Some(node) = date_format.atomic() { + (node.value, node.site) + } else { + return Err(ExpansionError::new( + &format!("`{}' macro needs string (or atomic) \ + formatting argument.", name), + site)) + }; + + let now = chrono::Local::now(); + let formatted = now.format(&date_format).to_string(); + Ok(vec![ParseNode::String(Node::new(&formatted, &site))]) + }, _ => Err(ExpansionError::new( &format!("Macro not found (`{}').", name), site))