grug

A static website generator written in Guile Scheme.
Log | Files | Refs | README | LICENSE

commit b0d83465e603ce565105a3e1bb06d1d440c1d5d3
parent bc7c554b3d412bc71c2f1ab95800b0abfb662deb
Author: Luke Willis <lukejw@loquat.dev>
Date:   Tue, 19 Aug 2025 20:36:29 -0400

Add build and publishing commands

Diffstat:
MMakefile.am | 1+
Mexample/grug.scm | 9+++++++--
Agrug/publishers.scm | 20++++++++++++++++++++
Mgrug/site.scm | 24+++++++++++++++++++-----
Mgrug/ui.scm | 8++++++--
Mguix.scm | 3++-
6 files changed, 55 insertions(+), 10 deletions(-)

diff --git a/Makefile.am b/Makefile.am @@ -25,6 +25,7 @@ bin_SCRIPTS = \ SOURCES = \ grug/builders.scm \ + grug/publishers.scm \ grug/readers.scm \ grug/site.scm \ grug/ui.scm \ diff --git a/example/grug.scm b/example/grug.scm @@ -1,7 +1,12 @@ (use-modules (grug site) - (grug builders)) + (grug builders) + (grug publishers)) (site #:metadata `((title . "Example Site")) #:builders (list (simple-pages "pages") (copy-directory "css") - (blog "posts" #:prefix "/blog"))) + (blog "posts" #:prefix "/blog")) + #:publishers (list (rsync-publisher #:user "lukejw" + #:host "loquat.dev" + #:destination "/var/www/htdocs/www.loquat.dev/" + #:flags (cons "--rsync-path=openrsync" %default-rsync-flags)))) diff --git a/grug/publishers.scm b/grug/publishers.scm @@ -0,0 +1,20 @@ +(define-module (grug publishers) + #:use-module (grug site) + #:export (rsync-publisher + %default-rsync-flags)) + +(define %default-rsync-flags + '("--delete" "--progress" "--recursive" "--verbose")) + +(define* (rsync-publisher #:key destination user host + (flags %default-rsync-flags)) + (lambda (site) + (let ((remote-path (cond + ((and user host) + (string-append user "@" host ":" destination)) + (host + (string-append host ":" destination)) + (else + destination))) + (output-path (string-append (site-build-directory site) "/"))) + (apply system* "rsync" (append flags (list output-path remote-path)))))) diff --git a/grug/site.scm b/grug/site.scm @@ -9,22 +9,27 @@ site-metadata site-reader site-builders - build-site)) + build-site + publish-site)) (define-record-type <site> - (make-site build-directory metadata reader builders) + (make-site build-directory metadata reader builders publishers) site? (build-directory site-build-directory) (metadata site-metadata) (reader site-reader) - (builders site-builders)) + (builders site-builders) + (publishers site-publishers)) (define* (site #:key (build-directory "site") (metadata `((title . "Grug Site"))) (reader cmark) - (builders '())) - (make-site build-directory metadata reader builders)) + (builders '()) + (publishers '())) + (make-site build-directory metadata reader builders publishers)) + +;; TODO: Make one simple interface for grug commands (define (build-site site) ;; Reset site build directory @@ -33,3 +38,12 @@ (mkdir (site-build-directory site)) ;; Run builders for site (for-each (cut <> site) (site-builders site))) + +(define (publish-site site) + ;; Reset site build directory + (when (file-exists? (site-build-directory site)) + (delete-file-recursively (site-build-directory site))) + (mkdir (site-build-directory site)) + ;; Run publishers for site + (for-each (cut <> site) (site-publishers site))) + diff --git a/grug/ui.scm b/grug/ui.scm @@ -2,6 +2,7 @@ (define-module (grug ui) #:declarative? #f + #:use-module (ice-9 match) #:use-module (ice-9 pretty-print) #:use-module (grug site) #:export (main)) @@ -23,5 +24,8 @@ as-is." (error "Configuration does not return site"))) (error "Configuration not found"))) -(define* (main prog . args) - (build-site (load-config "grug.scm"))) +(define* (main arg0 command . args) + (match command + (() (error "Args, please!!!\n")) + ("build" (build-site (load-config "grug.scm"))) + ("publish" (publish-site (load-config "grug.scm"))))) diff --git a/guix.scm b/guix.scm @@ -10,6 +10,7 @@ (gnu packages guile-xyz) (gnu packages pkg-config) (gnu packages markup) + (gnu packages rsync) (gnu packages version-control)) (package @@ -23,7 +24,7 @@ (delete 'strip)))) (native-inputs (list autoconf automake pkg-config)) (inputs (list guile-3.0)) - (propagated-inputs (list guile-lib cmark)) + (propagated-inputs (list guile-lib cmark rsync)) (synopsis "Functional static site generator") (description #f) (home-page #f)