2024-06-01 @rrobin
The tissue issue tracker stores issues as gemtext files in a git repository, it serves them as a web page and provides a CLI tool to manage them.
Gemtext is not a very powerfull format, it only supports text, bullet points, titles, links and blocks.
Tissue overcomes its limitations with some conventions. Metadata is encoded in bullet points, these have special meaning:
* tags: important * assigned: bruce * status: closed
The other convention encodes tasks, their description and state:
* [ ] buy groceries * [x] fix the car
There are also some shorthand forms e.g. this is also valid to close a ticket
* closed
Issues are read by the read-gemtext-issue function:
(define (read-gemtext-issue file) "Read issue from gemtext @var{file} and return an @code{} object." (let* ((file-document (read-gemtext-document file))
I am not familiar with guile's define-class, but these seem to be the components of an issue:
(define-class( ) (assigned #:accessor issue-assigned #:init-keyword #:assigned) (keywords #:accessor issue-keywords #:init-keyword #:keywords) (open? #:accessor issue-open? #:init-keyword #:open?) (tasks #:accessor issue-tasks #:init-keyword #:tasks) (completed-tasks #:accessor issue-completed-tasks #:init-keyword #:completed-tasks))
that is
I find this easier to read in the issue read function
(make#:path file ;; Fallback to filename if title has no alphabetic characters. #:title (let ((title (hashtable-ref file-details 'title ""))) (if (string-any char-set:letter title) title file)) #:assigned (hashtable-ref file-details 'assigned '()) ;; "closed" is a special keyword to indicate the open/closed ;; status of an issue. #:keywords (delete "closed" all-keywords) #:open? (not (member "closed" all-keywords)) #:tasks (hashtable-ref file-details 'tasks 0) #:completed-tasks (hashtable-ref file-details 'completed-tasks 0) #:commits (file-document-commits file-document) #:snippet-source-text (document-snippet-source-text file-document))))
That is the following information
The function that extracts this metatadata from the file is file-details
As the documentation states this function returns an hash-table, generated from the file contents:
(define (file-details port) "Return a hashtable of details extracted from input PORT reading a gemtext file." (let ((result (make-eq-hashtable))
I am not familiar with transducers in guile/scheme but port-transduce seems to be processing one line at a time (get-line-dos-or-unix) from the input and using the provided lambda on each line:
(port-transduce (tmap (lambda (line) (cond ;; Toggle preformatted state. ((string=? "```" line) (set! in-preformatted (not in-preformatted))) ;; Ignore preformatted blocks. (in-preformatted #t) ;; Checkbox lists are tasks. If the ;; checkbox has any character other ;; than space in it, the task is ;; completed.
this function goes along mutating the result hashtable
There are some special rules in place as well
;; Insert values based on ;; their keys. (for-each (match-lambda (((or 'assign 'assigned) . values) (hashtable-prepend! result 'assigned (map (cut resolve-alias <> (%aliases)) values))) (((or 'keyword 'keywords 'severity 'status 'priority 'tag 'tags 'type) . values) (hashtable-prepend! result 'keywords values))
Finally there is a search for keywords in lists of keywords separated by commas:
(string-contains element keyword)) (list "request" "bug" "critical" "enhancement" "progress" "testing" "later" "documentation" "help" "closed")))
There also a reference to file-document-commits that is used to get a list of commits that relate to the gemtext file. This is first seen in the file-document class definition
(define-class( ) (path #:accessor file-document-path #:init-keyword #:path) ;; List of objects, oldest first. (commits #:accessor file-document-commits #:init-keyword #:commits))
and it is initialized during document creation based on commits-affecting-file
(define (commits-affecting-file file) "Return a list of commits affecting @var{file} in current repository."
I did not look deeper into this but it seems to be derived from a map of files to related commits created by file-modification-table:
(define (file-modification-table repository) "Return a hashtable mapping files to the list of commits in REPOSITORY that modified them."
=> https://git.systemreboot.net/tissue/ | https://tissue.systemreboot.net/ | https://tissue.systemreboot.net/manual/dev/en/ | https://www.gnu.org/software/guile/manual/html_node/SRFI_002d171.html
text/gemini;
This content has been proxied by September (ba2dc).