From b11a04a4958f613d6159a0004addbeeadd516102 Mon Sep 17 00:00:00 2001
From: Arun Isaac
Date: Fri, 30 Aug 2019 12:32:55 +0530
Subject: Implement operation as structure.

* ennu.el (ennu-operation): New structure.
(ennu-publish-post, ennu-publish-page, ennu-publish-index,
ennu-publish-feed, ennu-publish-image, ennu-publish-copy,
ennu-publish-static-file, ennu--do-operation): Use new operation
structure API.
---
 ennu.el | 223 ++++++++++++++++++++++++++++++++++------------------------------
 1 file changed, 120 insertions(+), 103 deletions(-)

diff --git a/ennu.el b/ennu.el
index a07a5b8..5ee6be5 100644
--- a/ennu.el
+++ b/ennu.el
@@ -17,6 +17,10 @@
   filename author date language links
   summary tags thumbnail title translation-group)
 
+(cl-defstruct (ennu-operation (:constructor ennu-make-operation)
+                              (:copier nil))
+  inputs outputs publish)
+
 (defun ennu-posts (posts-directory)
   (sort (seq-map 'ennu-read-post
                  (file-expand-wildcards
@@ -84,11 +88,6 @@ last form in BODY."
 
 (defun ennu-publish-post (post)
   ;; TODO: Tangle post
-  `((,(ennu-post-filename post))
-    (,(ennu--org-output-filename (ennu-post-filename post)))
-    ,(lambda (output-file)
-       (ennu-with-file-contents (ennu-post-filename post)
-         (org-export-to-file 'ennu-html output-file))
        ;; (when-let (tangle-dir (or (plist-get posts-plist :valai-tangle-directory)
        ;;                           valai-tangle-directory))
        ;;   (dolist (tangled-file
@@ -100,17 +99,23 @@ last form in BODY."
        ;;                  (expand-file-name (file-name-nondirectory tangled-file)
        ;;                                    tangle-dir)
        ;;                  t)))
-       )))
+  (ennu-make-operation
+   :inputs (list (ennu-post-filename post))
+   :outputs (list (ennu--org-output-filename (ennu-post-filename post)))
+   :publish (lambda (output-file)
+              (ennu-with-file-contents (ennu-post-filename post)
+                (org-export-to-file 'ennu-html output-file)))))
 
 (defun ennu-publish-page (pages-directory page)
-  `((,page)
-    (,(ennu--org-output-filename
-       (string-remove-prefix
-        (file-name-as-directory pages-directory)
-        page)))
-    ,(lambda (output-file)
-       (ennu-with-file-contents page
-         (org-export-to-file 'html output-file)))))
+  (ennu-make-operation
+   :inputs (list page)
+   :outputs (list (ennu--org-output-filename
+                   (string-remove-prefix
+                    (file-name-as-directory pages-directory)
+                    page)))
+   :publish (lambda (output-file)
+              (ennu-with-file-contents page
+                (org-export-to-file 'html output-file)))))
 
 (defun ennu-video-poster (video)
   (pcase (directory-files (ennu-setting :images-directory) nil
@@ -139,48 +144,50 @@ last form in BODY."
   (let* ((tongue (ennu-post-language (first posts)))
          (number-of-pages (ceiling (length posts) posts-per-page))
          (page-numbers (number-sequence 1 number-of-pages)))
-    `(,(seq-map 'ennu-post-filename posts)
-      ,(cons (ennu-add-tongue-suffix (format "%s.html" filename-prefix) tongue)
-             (seq-map (apply-partially 'ennu-index-filename filename-prefix tongue "html")
-                      page-numbers))
-      ,(lambda (home-page &rest output-files)
-         (seq-mapn
-          (lambda (posts page-number output-file)
-            (with-temp-buffer
-              (insert (format "#+TITLE: %s\n" title))
-              (insert (format "#+LANGUAGE: %s\n" tongue))
-              (insert "#+OPTIONS: num:nil toc:nil\n\n")
-              (seq-do (lambda (post)
-                        (insert (format "* [[post:%s]]\n" (file-name-base (ennu-post-filename post))))
-                        (insert (format-time-string
-                                 "/%b %e, %Y/\n\n"
-                                 (ennu-post-date post)))
-                        (when-let ((thumbnail (ennu-post-thumbnail post)))
-                          (insert (format "[[thumbnail:%s]]\n\n" thumbnail)))
-                        (when-let ((summary (ennu-post-summary post)))
-                          (insert summary)
-                          (insert "\n\n"))
-                        (when-let ((tags (ennu-post-tags post)))
-                          (insert "Tags: ")
-                          (insert
-                           (string-join (seq-map (apply-partially 'format "[[tag:%s]]")
-                                                 tags)
-                                        ", "))
-                          (insert "\n\n")))
-                      posts)
-              (unless (= page-number 1)
-                (insert (format "[[./%s][Newer posts]]\n"
-                                (ennu-index-filename (file-name-nondirectory filename-prefix)
-                                                     tongue nil (1- page-number)))))
-              (unless (= page-number number-of-pages)
-                (insert (format "[[./%s][Older posts]]\n"
-                                (ennu-index-filename (file-name-nondirectory filename-prefix)
-                                                     tongue nil (1+ page-number)))))
-              (org-export-to-file 'ennu-html output-file)))
-          (seq-partition posts posts-per-page)
-          page-numbers
-          output-files)
-         (copy-file (first output-files) home-page)))))
+    (ennu-make-operation
+     :inputs (seq-map 'ennu-post-filename posts)
+     :outputs (cons (ennu-add-tongue-suffix (format "%s.html" filename-prefix) tongue)
+                    (seq-map (apply-partially 'ennu-index-filename filename-prefix tongue "html")
+                             page-numbers))
+     :publish
+     (lambda (home-page &rest output-files)
+       (seq-mapn
+        (lambda (posts page-number output-file)
+          (with-temp-buffer
+            (insert (format "#+TITLE: %s\n" title))
+            (insert (format "#+LANGUAGE: %s\n" tongue))
+            (insert "#+OPTIONS: num:nil toc:nil\n\n")
+            (seq-do (lambda (post)
+                      (insert (format "* [[post:%s]]\n" (file-name-base (ennu-post-filename post))))
+                      (insert (format-time-string
+                               "/%b %e, %Y/\n\n"
+                               (ennu-post-date post)))
+                      (when-let ((thumbnail (ennu-post-thumbnail post)))
+                        (insert (format "[[thumbnail:%s]]\n\n" thumbnail)))
+                      (when-let ((summary (ennu-post-summary post)))
+                        (insert summary)
+                        (insert "\n\n"))
+                      (when-let ((tags (ennu-post-tags post)))
+                        (insert "Tags: ")
+                        (insert
+                         (string-join (seq-map (apply-partially 'format "[[tag:%s]]")
+                                               tags)
+                                      ", "))
+                        (insert "\n\n")))
+                    posts)
+            (unless (= page-number 1)
+              (insert (format "[[./%s][Newer posts]]\n"
+                              (ennu-index-filename (file-name-nondirectory filename-prefix)
+                                                   tongue nil (1- page-number)))))
+            (unless (= page-number number-of-pages)
+              (insert (format "[[./%s][Older posts]]\n"
+                              (ennu-index-filename (file-name-nondirectory filename-prefix)
+                                                   tongue nil (1+ page-number)))))
+            (org-export-to-file 'ennu-html output-file)))
+        (seq-partition posts posts-per-page)
+        page-numbers
+        output-files)
+       (copy-file (first output-files) home-page)))))
 
 (defun ennu--absolute-uri (path)
   (format "%s://%s/%s"
@@ -192,22 +199,24 @@ last form in BODY."
   (format-time-string "%Y-%m-%dT%H:%M:%SZ" date))
 
 (defun ennu-publish-feed (feed-file title rights posts)
-  `(,(seq-map 'ennu-post-filename posts)
-    (,feed-file)
-    ,(lambda (output-file)
-       (with-temp-file output-file
-         (insert
-          (xmlgen
-           `(feed :xmlns "http://www.w3.org/2005/Atom"
-                  (id ,(ennu--absolute-uri ""))
-                  (title ,title)
-                  (updated ,(ennu--atom-date (ennu-post-date (first posts))))
-                  (link :rel "self" :href ,(ennu--absolute-uri feed-file))
-                  (generator
-                   ,(format "Emacs %d.%d Org-mode %s ennu %s"
-                            emacs-major-version emacs-minor-version (org-version) ennu-version))
-                  (rights ,rights)
-                  ,@(seq-map 'ennu--feed-entry posts))))))))
+  (ennu-make-operation
+   :inputs (seq-map 'ennu-post-filename posts)
+   :outputs (list feed-file)
+   :publish
+   (lambda (output-file)
+     (with-temp-file output-file
+       (insert
+        (xmlgen
+         `(feed :xmlns "http://www.w3.org/2005/Atom"
+                (id ,(ennu--absolute-uri ""))
+                (title ,title)
+                (updated ,(ennu--atom-date (ennu-post-date (first posts))))
+                (link :rel "self" :href ,(ennu--absolute-uri feed-file))
+                (generator
+                 ,(format "Emacs %d.%d Org-mode %s ennu %s"
+                          emacs-major-version emacs-minor-version (org-version) ennu-version))
+                (rights ,rights)
+                ,@(seq-map 'ennu--feed-entry posts))))))))
 
 (defun ennu--feed-entry (post)
   (let ((link (ennu--absolute-uri (ennu--org-output-filename
@@ -270,17 +279,22 @@ last form in BODY."
   (concat (file-name-as-directory directory) name))
 
 (defun ennu-publish-image (widths image)
-  `((,image)
-    ,(seq-map (apply-partially 'ennu-image-output-filename image)
-              widths)
-    ,(lambda (&rest output-files)
-       (seq-mapn (lambda (output-file width)
-                   (ennu-image-optimize-image
-                    (ennu-image-resize-image image output-file width)))
-                 output-files widths))))
+  (ennu-make-operation
+   :inputs (list image)
+   :outputs (seq-map (apply-partially 'ennu-image-output-filename image)
+                     widths)
+   :publish
+   (lambda (&rest output-files)
+     (seq-mapn (lambda (output-file width)
+                 (ennu-image-optimize-image
+                  (ennu-image-resize-image image output-file width)))
+               output-files widths))))
 
 (defun ennu-publish-copy (file)
-  `((,file) (,file) ,(apply-partially 'copy-file file)))
+  (ennu-make-operation
+   :inputs (list file)
+   :outputs (list file)
+   :publish (apply-partially 'copy-file file)))
 
 (defun newest-file (files)
   (pcase files
@@ -301,30 +315,33 @@ last form in BODY."
     (copy-file source destination)))
 
 (defun ennu--do-operation (temporary-directory operation)
-  (let ((expand (lambda (directory file)
-                  (expand-file-name file directory))))
-    (pcase operation
-      (`(,input-files ,output-files ,publish)
-       (let ((absolute-output-files
-              (seq-map (apply-partially expand temporary-directory)
-                       output-files))
-             (previous-output-files
-              (seq-map (apply-partially expand (ennu-setting :output-directory))
-                       output-files)))
-         (cond
-          ((and (seq-every-p 'file-exists-p previous-output-files)
-                (file-newer-than-file-p (newest-file previous-output-files)
-                                        (newest-file input-files)))
-           (message "Skipping publishing %s to %s" input-files output-files)
-           (seq-mapn 'ennu-copy previous-output-files absolute-output-files))
-          (t (message "Publishing %s to %s" input-files output-files)
-             (seq-do 'ennu-mkdir-p
-                     (seq-uniq
-                      (seq-map 'file-name-directory absolute-output-files)))
-             (apply publish absolute-output-files))))))))
+  (let* ((expand (lambda (directory file)
+                   (expand-file-name file directory)))
+         (inputs (ennu-operation-inputs operation))
+         (outputs (ennu-operation-outputs operation))
+         (absolute-outputs
+          (seq-map (apply-partially expand temporary-directory)
+                   outputs))
+         (previous-outputs
+          (seq-map (apply-partially expand (ennu-setting :output-directory))
+                   outputs)))
+    (cond
+     ((and (seq-every-p 'file-exists-p previous-outputs)
+           (file-newer-than-file-p (newest-file previous-outputs)
+                                   (newest-file inputs)))
+      (message "Skipping publishing %s to %s" inputs outputs)
+      (seq-mapn 'ennu-copy previous-outputs absolute-outputs))
+     (t (message "Publishing %s to %s" inputs outputs)
+        (seq-do 'ennu-mkdir-p
+                (seq-uniq
+                 (seq-map 'file-name-directory absolute-outputs)))
+        (apply (ennu-operation-publish operation) absolute-outputs)))))
 
 (defun ennu-publish-static-file (file)
-  `((,file) (,file) ,(apply-partially 'copy-file file)))
+  (ennu-make-operation
+   :inputs (list file)
+   :outputs (list file)
+   :publish (apply-partially 'copy-file file)))
 
 (defun ennu-publish-link (link)
   (pcase link
-- 
cgit v1.2.3