Added support for categories.
2 files changed, 83 insertions(+), 6 deletions(-)

M opel.el
M pelican.org
M opel.el +27 -3
@@ 707,6 707,7 @@ 
 (defvar opel-overwrite-all t "Whether to delete all ~opel~ generated files and write afresh, even if those posts have not been modified since the last export.")
 (defvar opel-export-newcommands nil "Set to non-nil to export LaTeX newcommand directives.  Note that this significantly slows down export for large blogs.")
 (defvar opel-metadata-keys nil "List of Pelican metadata keys you would like added to a post. Do NOT put category, status or tags in here as they are handled through other means.")
+
 (defun opel--get-keys-from-ht (ht)
   "Get a list of keys from a hash table."
   (let ((keys nil))

          
@@ 754,6 755,16 @@ 
   (let ((inherit (when INHERIT 'selective)))
     (org-entry-get (point) prop-name inherit)))
 
+(defun opel--get-category ()
+  "Get the category of a node."
+  (let* ((default-category
+	   (file-name-sans-extension (file-name-nondirectory buffer-file-name)))
+	 (category (org-get-category))
+	 (is-default (string= category default-category)))
+    (if is-default
+	""
+      category)))
+
 (defun opel--build-level-regexp (level)
   "Build the regular expression to match the number of stars in a heading."
   (mapconcat #'identity (cons "^" (make-list level "\\*")) ""))

          
@@ 774,6 785,7 @@ 
 	     (custom-id (opel--get-property "CUSTOM_ID"))
 	     (id (org-id-get-create))
 	     (file-metadata (opel--get-file-metadata))
+	     (category (opel--get-category))
 	     (body (opel--get-node-text)))
 	 (push `((title ,title)
 		 (date ,date)

          
@@ 783,6 795,7 @@ 
 		 (custom-id ,custom-id)
 		 (id ,id)
 		 (file-metadata ,file-metadata)
+		 (category ,category)
 		 (body ,body))
 	       metadata)))
      "PELICAN_TYPE=\"article\"|PELICAN_TYPE=\"page\""

          
@@ 814,6 827,13 @@ 
 	(format ":tags: %s" tags)
       "")))
 
+(defun opel--make-post-category (post-metadata)
+  "Construct the category of the post."
+  (let ((category (car (alist-get 'category post-metadata))))
+    (if (string= category "")
+	""
+      (format ":category: %s" category))))
+
 (defun opel--make-post-file-metadata (post-metadata)
   "Construct the file metadata for the post."
   (let* ((metadata (car (alist-get 'file-metadata post-metadata)))

          
@@ 879,11 899,12 @@ LATEX_HEADERs."
 	(date (opel--make-post-date post-metadata))
 	(status (opel--make-post-status post-metadata))
 	(metadata (opel--make-post-file-metadata post-metadata))
+	(category (opel--make-post-category post-metadata))
 	(tags (opel--make-post-tags post-metadata)))
 	;; (newcommands (opel--make-newcommands)))
     (format
-     "%s\n%s\n#+BEGIN_EXPORT rst\n%s\n%s\n%s\n%s\n\n#+END_EXPORT\n\n%s\n"
-     title date tags status metadata newcommands body)))
+     "%s\n%s\n#+BEGIN_EXPORT rst\n%s\n%s\n%s\n%s\n%s\n\n#+END_EXPORT\n\n%s\n"
+     title date tags status category metadata newcommands body)))
 	
 (defun opel--convert-post-to-rst (post-string filename)
   "Convert the string of the post to restructured text."

          
@@ 1020,7 1041,8 @@ Return the list of results."
 	 (body (car (alist-get 'body post-metadata)))
 	 (id (car (alist-get 'id post-metadata)))
 	 (metadata (opel--make-post-file-metadata post-metadata))
-	 (text (concat title type status tags id metadata body)))
+	 (category (car (alist-get 'category post-metadata)))
+	 (text (concat title type status tags id metadata category body)))
     (secure-hash 'md5 text)))
 
 (defun opel--add-md5 ()

          
@@ 1035,6 1057,7 @@ Return the list of results."
 	      (tags (opel--get-tags))
 	      (body (opel--get-node-text))
 	      (id (org-id-get-create))
+	      (category (opel--get-category))
 	      (file-metadata (opel--get-file-metadata))
 	      (metadata `((title ,title)
 			  (date ,date)

          
@@ 1042,6 1065,7 @@ Return the list of results."
 			  (tags ,tags)
 			  (status ,status)
 			  (id ,id)
+			  (category ,category)
 			  (file-metadata ,file-metadata)
 			  (body ,body)))
 	      (new-md5 (opel--compute-md5 metadata))

          
M pelican.org +56 -3
@@ 10,6 10,7 @@ 
 - Tag inheritance to assist in organization (e.g. Create a "Soccer"
   heading and tag it with ~soccer~ - all posts under it will inherit the
   tag)
+- Categories
 - Only write posts that have been modified
 - LaTeX equations in your posts
 - Support for hidden pages

          
@@ 19,6 20,7 @@ 
 - Use Restructured Text Features
 - Verbatim Test
 - Syntax highlighted source code
+- [[https://docs.getpelican.com/en/latest/content.html#file-metadata][File Metadata]]
 ** Prerequisites
 You must have [[https://pandoc.org/][pandoc]] installed and in your path.
 ** Configuration

          
@@ 120,6 122,10 @@ Each Org mode tag is transformed by the 
   tags).
 
 Feel free to add your own transformations.
+*** Categories
+Create a ~CATEGORY~ property in your post. Note that Org mode inherits
+this property, so you could place it at a top level heading so that all
+your posts under that heading automatically have this category.
 *** Preventing Export of Certain Headlines
 If you want to exclude a headline (and all its children) from export,
 tag it with the value of the ~opel-no-export~ variable.

          
@@ 310,6 316,7 @@ Here are all the function definitions.
 <<get-tags-def>>
 <<get-headline-def>>
 <<get-property-def>>
+<<get-category-def>>
 <<build-level-regexp>>
 <<get-all-pelican-nodes-metadata-def>>
 <<get-file-metadata>>

          
@@ 317,6 324,7 @@ Here are all the function definitions.
 <<get-title-string>>
 <<get-date-string>>
 <<get-tags-string>>
+<<get-category-string>>
 <<get-file-metadata-string>>
 <<get-body-string>>
 <<get-newcommands-string>>

          
@@ 1072,6 1080,7 @@ These variables need to be defined:
 (defvar opel-overwrite-all t "Whether to delete all ~opel~ generated files and write afresh, even if those posts have not been modified since the last export.")
 (defvar opel-export-newcommands nil "Set to non-nil to export LaTeX newcommand directives.  Note that this significantly slows down export for large blogs.")
 (defvar opel-metadata-keys nil "List of Pelican metadata keys you would like added to a post. Do NOT put category, status or tags in here as they are handled through other means.")
+
 #+END_SRC
 
 #+RESULTS: variables

          
@@ 1175,6 1184,28 @@ space.
 
 #+RESULTS:
 
+** Get the Category of a Node
+By default, all nodes have a category: The base file name. We don't want
+all nodes to have this category when none is explicitly supplied. So we
+check for it and return an empty string.
+
+#+name: get-category-def
+#+BEGIN_SRC emacs-lisp 
+(defun opel--get-category ()
+  "Get the category of a node."
+  (let* ((default-category
+	   (file-name-sans-extension (file-name-nondirectory buffer-file-name)))
+	 (category (org-get-category))
+	 (is-default (string= category default-category)))
+    (if is-default
+	""
+      category)))
+
+#+END_SRC
+
+#+RESULTS: get-category-def
+: opel--get-category
+
 ** Get the Body of a Node
 This gets the body of a node and all subtrees, sans the metadata.
 

          
@@ 1280,6 1311,7 @@ The code snippet below will extract the 
 	     (custom-id (opel--get-property "CUSTOM_ID"))
 	     (id (org-id-get-create))
 	     (file-metadata (opel--get-file-metadata))
+	     (category (opel--get-category))
 	     (body (opel--get-node-text)))
 	 (push `((title ,title)
 		 (date ,date)

          
@@ 1289,6 1321,7 @@ The code snippet below will extract the 
 		 (custom-id ,custom-id)
 		 (id ,id)
 		 (file-metadata ,file-metadata)
+		 (category ,category)
 		 (body ,body))
 	       metadata)))
      "PELICAN_TYPE=\"article\"|PELICAN_TYPE=\"page\""

          
@@ 1390,6 1423,21 @@ delimited string.
 : opel--make-post-file-metadata
 
 
+*** Construct Category
+#+name: get-category-string
+#+BEGIN_SRC emacs-lisp 
+(defun opel--make-post-category (post-metadata)
+  "Construct the category of the post."
+  (let ((category (car (alist-get 'category post-metadata))))
+    (if (string= category "")
+	""
+      (format ":category: %s" category))))
+
+#+END_SRC
+
+#+RESULTS: get-category-string
+: opel--make-post-category
+
 *** Construct Body
 
 #+name: get-body-string

          
@@ 1554,11 1602,12 @@ LATEX_HEADERs."
 	(date (opel--make-post-date post-metadata))
 	(status (opel--make-post-status post-metadata))
 	(metadata (opel--make-post-file-metadata post-metadata))
+	(category (opel--make-post-category post-metadata))
 	(tags (opel--make-post-tags post-metadata)))
 	;; (newcommands (opel--make-newcommands)))
     (format
-     "%s\n%s\n#+BEGIN_EXPORT rst\n%s\n%s\n%s\n%s\n\n#+END_EXPORT\n\n%s\n"
-     title date tags status metadata newcommands body)))
+     "%s\n%s\n#+BEGIN_EXPORT rst\n%s\n%s\n%s\n%s\n%s\n\n#+END_EXPORT\n\n%s\n"
+     title date tags status category metadata newcommands body)))
 	
 #+END_SRC
 *** Convert Post to Restructured Text

          
@@ 1812,6 1861,7 @@ combined:
 - tags
 - body
 - id
+- category
 - Any data_ properties (i.e. file metadata)
 
 If any of these entities change, then we need to ensure the file is

          
@@ 1834,7 1884,8 @@ modified post.
 	 (body (car (alist-get 'body post-metadata)))
 	 (id (car (alist-get 'id post-metadata)))
 	 (metadata (opel--make-post-file-metadata post-metadata))
-	 (text (concat title type status tags id metadata body)))
+	 (category (car (alist-get 'category post-metadata)))
+	 (text (concat title type status tags id metadata category body)))
     (secure-hash 'md5 text)))
 
 (defun opel--add-md5 ()

          
@@ 1849,6 1900,7 @@ modified post.
 	      (tags (opel--get-tags))
 	      (body (opel--get-node-text))
 	      (id (org-id-get-create))
+	      (category (opel--get-category))
 	      (file-metadata (opel--get-file-metadata))
 	      (metadata `((title ,title)
 			  (date ,date)

          
@@ 1856,6 1908,7 @@ modified post.
 			  (tags ,tags)
 			  (status ,status)
 			  (id ,id)
+			  (category ,category)
 			  (file-metadata ,file-metadata)
 			  (body ,body)))
 	      (new-md5 (opel--compute-md5 metadata))