summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--tissue/issue.scm82
1 files changed, 57 insertions, 25 deletions
diff --git a/tissue/issue.scm b/tissue/issue.scm
index 59e7ee9..95edf4e 100644
--- a/tissue/issue.scm
+++ b/tissue/issue.scm
@@ -85,6 +85,33 @@ strings, and return them as a list."
   "Remove PREFIX from STR."
   (substring str (string-length prefix)))
 
+(define (<=n-words? str n)
+  "Return #t if STR has N words or less. Else, return #f."
+  (<= (length (string-split str #\space))
+      n))
+
+(define (list-line->alist line)
+  "Split list LINE such as \"assigned: foo, keywords: fubar, bar\"
+into an association list of key-value pairs. Keys are symbols. Values
+are lists of strings. If LINE does not contain such key-value pairs,
+return #f."
+  (and (string-match "^\\* [a-zA-Z]+:" line)
+       (fold (lambda (element result)
+               (cond
+                ((string-match "^([a-zA-Z]+):[ ]*(.*)" element)
+                 => (lambda (m)
+                      (cons (list (string->symbol
+                                   (string-downcase (match:substring m 1)))
+                                  (match:substring m 2))
+                            result)))
+                (else
+                 (match result
+                   (((key . values) tail ...)
+                    (cons (cons key (cons element values))
+                          tail))))))
+             '()
+             (comma-split (remove-prefix "* " line)))))
+
 (define (file-details file)
   "Return a hashtable of details extracted from gemini FILE."
   (let ((result (make-eq-hashtable)))
@@ -95,26 +122,40 @@ strings, and return them as a list."
 	(lambda (port)
           (port-transduce (tmap (lambda (line)
                                   (cond
-                                   ;; Lists with the assigned: prefix
-                                   ;; specify assignees.
-                                   ((string-prefix? "* assigned:" line)
-                                    (hashtable-append! result 'assigned
-						       (comma-split
-							(remove-prefix "* assigned:" line))))
-                                   ;; Lists with the keywords: prefix
-                                   ;; specify keywords.
-                                   ((string-prefix? "* keywords:" line)
-                                    (hashtable-append! result 'keywords
-						       (comma-split
-							(remove-prefix "* keywords:" line))))
+                                   ;; Checkbox lists are tasks. If the
+                                   ;; checkbox has any character other
+                                   ;; than space in it, the task is
+                                   ;; completed.
+                                   ((string-match "^\\* \\[(.)\\]" line)
+                                    => (lambda (m)
+					 (hashtable-update! result 'tasks 1+ 0)
+					 (unless (string=? (match:substring m 1) " ")
+                                           (hashtable-update! result 'completed-tasks 1+ 0))))
+                                   ((let ((alist (list-line->alist line)))
+                                      (and alist
+                                           ;; Every value string is 2
+                                           ;; words or less.
+                                           (every (match-lambda
+                                                    ((_ . values)
+                                                     (every (cut <=n-words? <> 2)
+                                                            values)))
+                                                  alist)
+                                           alist))
+                                    => (lambda (alist)
+                                         ;; Insert values based on
+                                         ;; their keys.
+                                         (for-each (match-lambda
+                                                     (((or 'assign 'assigned) . values)
+                                                      (hashtable-append! result 'assigned values))
+                                                     (((or 'keywords 'severity 'status 'priority 'tags 'type) . values)
+                                                      (hashtable-append! result 'keywords values))
+                                                     (_ #t))
+                                                   alist)))
                                    ;; A more fuzzy heuristic to find keywords
                                    ((and (string-prefix? "* " line)
 					 ;; Is every comma-separated
 					 ;; element two words utmost?
-					 (every (lambda (element)
-                                                  (<= (length
-						       (string-split element #\space))
-						      2))
+					 (every (cut <=n-words? <> 2)
 						(comma-split (remove-prefix "* " line)))
 					 ;; Does any comma-separated
 					 ;; element contain a potential
@@ -130,15 +171,6 @@ strings, and return them as a list."
                                     (hashtable-append! result 'keywords
 						       (comma-split
 							(remove-prefix "* " line))))
-                                   ;; Checkbox lists are tasks. If the
-                                   ;; checkbox has any character other
-                                   ;; than space in it, the task is
-                                   ;; completed.
-                                   ((string-match "^\\* \\[(.)\\]" line)
-                                    => (lambda (m)
-					 (hashtable-update! result 'tasks 1+ 0)
-					 (unless (string=? (match:substring m 1) " ")
-                                           (hashtable-update! result 'completed-tasks 1+ 0))))
                                    ;; The first level one heading is the
                                    ;; title.
                                    ((string-prefix? "# " line)