changelog shortlog graph tags branches changeset files file revisions raw help

Mercurial > core / annotate lisp/lib/organ/pkg.lisp

changeset 96: 301fd45bbe73
parent: 17b6d1f39506
child: d0b235557fab
author: ellis <ellis@rwest.io>
date: Wed, 13 Dec 2023 20:02:36 -0500
permissions: -rw-r--r--
description: big refactor of lisp code
64
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
1
 ;;; organ.lisp --- Org parser
93
17b6d1f39506 rdb refactor, skel stuff
ellis <ellis@rwest.io>
parents: 64
diff changeset
2
 (defpackage :organ
96
301fd45bbe73 big refactor of lisp code
ellis <ellis@rwest.io>
parents: 93
diff changeset
3
   (:use :cl :cl-ppcre :std)
64
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
4
   (:shadowing-import-from :sb-gray :fundamental-stream)
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
5
   (:import-from :uiop :read-file-string)
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
6
   (:export
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
7
    ;; params
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
8
    :*org-todo-keyword-types*
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
9
    :*org-todo-keywords*
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
10
    ;; vars
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
11
    :org-todo-keyword-map
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
12
    :org-heading-regexp
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
13
    :org-file-property-regexp
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
14
    :org-todo-keyword-regexp
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
15
    :org-property-regexp
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
16
    :org-tag-regexp
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
17
    :org-element-types
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
18
    :org-element-objects
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
19
    ;; proto
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
20
    :org-parse
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
21
    :org-parse-lines
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
22
    ;; classes
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
23
    :org-element
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
24
    :text
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
25
    :org-kind
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
26
    :org-file
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
27
    :org-lines
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
28
    :o-lines
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
29
    :org-stream
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
30
    :org-headline
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
31
    :level
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
32
    :props
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
33
    :tags
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
34
    :title
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
35
    :state
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
36
    :org-todo-keyword
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
37
    :todo-type
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
38
    :org-list
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
39
    :org-tag
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
40
    ;; fns
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
41
    :org-todo-keyword-p
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
42
    :org-tag-split
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
43
    :read-org-file
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
44
    :read-org-lines
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
45
    :read-org-lines-from-string
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
46
    :make-org-headline
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
47
    :make-org-todo-keyword
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
48
    :make-org-tag
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
49
    ;; macs
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
50
    :org-init))
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
51
 
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
52
 (in-package :organ)
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
53
 
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
54
 (defparameter *org-todo-keyword-types*
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
55
   '(todo wip done))
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
56
 
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
57
 (defparameter *org-todo-keywords*
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
58
   '(("TODO" todo) ("DONE" done) ("FIND" todo) ("FOUND" done)
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
59
     ("RESEARCH" todo) ("RECORD" todo) ("OUTLINE" todo) ("DRAFT" todo)
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
60
     ("REVIEW" todo) ("FIX" todo) ("IMPL" todo) ("TEST" todo) ("FIXED" done)
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
61
     ("GOTO" todo) ("HACK" todo) ("NOTE" todo) ("CODE" todo) ("LINK" todo))
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
62
   "List of keywords accepted by `organ'. ")
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
63
 
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
64
 (defun org-todo-keyword-map ()
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
65
   (let ((kws (make-hash-table :size 20)))
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
66
     (dolist (kw *org-todo-keywords*)
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
67
       (let ((k (intern (car kw)))
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
68
 	    (v (cadr kw)))
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
69
 	(assert (member v *org-todo-keyword-types*))
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
70
 	(setf (gethash k kws) v)))
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
71
     kws))
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
72
 
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
73
 (defvar org-todo-keyword-map (org-todo-keyword-map))
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
74
 
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
75
 (defmacro org-todo-keyword-p (kw)
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
76
   "Search for symbol KW in `org-todo-keyword-map' returning the
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
77
 associated value or nil if not found."
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
78
   `(gethash (intern ,kw) org-todo-keyword-map))
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
79
 
93
17b6d1f39506 rdb refactor, skel stuff
ellis <ellis@rwest.io>
parents: 64
diff changeset
80
 (defvar org-headline-regexp "^([*]+)\\s+(.*)$")
17b6d1f39506 rdb refactor, skel stuff
ellis <ellis@rwest.io>
parents: 64
diff changeset
81
 (defvar org-todo-keyword-regexp "^(\\w+)\\s+(.*)$")
17b6d1f39506 rdb refactor, skel stuff
ellis <ellis@rwest.io>
parents: 64
diff changeset
82
 (defvar org-file-property-regexp "^[#+](.*)[:]\\s+(.*)$")
17b6d1f39506 rdb refactor, skel stuff
ellis <ellis@rwest.io>
parents: 64
diff changeset
83
 (defvar org-property-regexp "^[:](.*)[:]\\s+(.*)$")
17b6d1f39506 rdb refactor, skel stuff
ellis <ellis@rwest.io>
parents: 64
diff changeset
84
 
64
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
85
 ;; this doesn't consume leading whitespace. It could be useful in the
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
86
 ;; future to infer a value for org-tags-column but is contained in the
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
87
 ;; title slot of `org-headline' for now. The result of this scan is a
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
88
 ;; single string delimited by the ':' character. To get a list of tags
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
89
 ;; as strings, use `org-tag-split'.
93
17b6d1f39506 rdb refactor, skel stuff
ellis <ellis@rwest.io>
parents: 64
diff changeset
90
 (defvar org-tag-regexp "(:[\\w_@#%:]+:)$")
64
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
91
 
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
92
 (defun org-tag-split (tags)
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
93
   (remove-if (lambda (s) (typep s '(string 0))) (cl-ppcre:split ":" tags)))
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
94
 
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
95
 (defvar org-element-types
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
96
   '(babel-call center-block clock comment comment-block diary-sexp drawer
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
97
     dynamic-block example-block export-block fixed-width footnote-definition
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
98
     headline horizontal-rule inlinetask item keyword latex-environment
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
99
     node-property paragraph plain-list planning property-drawer quote-block
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
100
     section special-block src-block table table-row verse-block)
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
101
   "List of all org-element types provided by org-element.el in 'org-element-all-elements'")
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
102
 
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
103
 (defvar org-element-objects
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
104
   '(bold citation citation-reference code entity export-snippet
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
105
     footnote-reference inline-babel-call inline-src-block italic
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
106
     line-break latex-fragment link macro radio-target statistics-cookie
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
107
     strike-through subscript superscript table-cell target timestamp underline verbatim)
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
108
   "List of all org-element objects provided by org-element.el in 'org-element-all-objects'")
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
109
 
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
110
 (defgeneric org-parse (self)
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
111
   (:documentation "Parse the text slot from ORG-ELEMENT."))
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
112
 
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
113
 (defgeneric org-parse-lines (self)
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
114
   (:documentation "Parse the text slot from ORG-ELEMENT as a vector of lines."))
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
115
 
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
116
 (defmacro org-init (class &optional text)
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
117
   "Initialize a instance of `org-element' CLASS with optional TEXT."
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
118
   `(make-instance ',class :text ,(or text "")))
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
119
 
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
120
 ;; parent and children are implicit. A single instance of
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
121
 ;; `org-element' contains a complete org-mode AST.
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
122
 (defclass org-element ()
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
123
   ((text :initarg :text :accessor text :type string)
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
124
    (kind :initarg :kind :accessor org-kind :type keyword)))
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
125
 
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
126
 (defmethod org-parse-lines ((self org-element))
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
127
   (let ((lines (o-lines (read-org-lines-from-string (slot-value self 'text)))))
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
128
   (loop for i from 1 for x across lines
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
129
 	collect
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
130
 	(if (cl-ppcre:scan org-headline-regexp x) (list i (symb 'headline) x)
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
131
 	    (if (cl-ppcre:scan org-file-property-regexp x) (list i 'file-property x)
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
132
 		(if (cl-ppcre:scan org-property-regexp x) (list i 'node-property x)
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
133
 		    (list i nil x)))))))
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
134
 
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
135
 (defclass org-stream (fundamental-stream)
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
136
   ((stream :initarg :stream :reader stream-of)))
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
137
 
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
138
 (defclass org-file (org-element org-stream)
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
139
   ((path :initarg :path :accessor path)
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
140
    (kind :allocation :class :initform :file)))
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
141
 
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
142
 (defun read-org-file (path)
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
143
   (make-instance 'org-file :path path :text (read-file-string path)))
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
144
 
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
145
 ;; (slot-value (read-org-file "~/org/notes.org") 'text)
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
146
 
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
147
 (defclass org-lines (org-element)
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
148
   ((lines :initarg :lines :type vector :accessor o-lines)
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
149
    (kind :allocation :class :initform :org-lines)))
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
150
 
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
151
 (defun read-org-lines (&optional stream)
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
152
   (let ((slice (make-instance 'org-lines)))
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
153
     (setf (o-lines slice)
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
154
 	  (apply #'vector
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
155
 		 (loop for l = (read-line stream nil :eof)
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
156
 		       until (eq l :eof)
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
157
 		       collect l)))
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
158
     slice))
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
159
 
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
160
 (defun read-org-lines-from-string (str)
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
161
   (with-input-from-string (s str) (read-org-lines s)))
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
162
 
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
163
 ;; when level=0, headline is uninitialized
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
164
 (defclass org-headline (org-element)
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
165
   ((kind :allocation :class :initform :org-headline)
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
166
    (state :accessor state :initform nil)
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
167
    (level :accessor level :initform 0)
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
168
    (props :accessor props :initform nil)
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
169
    (priority :accessor priority :initform nil)
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
170
    (tags :accessor tags :initform nil)
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
171
    (title :accessor title :initform "")))
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
172
 
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
173
 (defun make-org-headline (text)
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
174
   (org-init org-headline text))
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
175
 
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
176
 (defmethod org-parse ((self org-headline))
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
177
   (with-input-from-string (s (text self))
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
178
     (when (peek-char #\* s) ;; start headline
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
179
       (let ((line (read-line s)))
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
180
 	(multiple-value-bind (start _ reg-start reg-end)
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
181
 	    ;; scan for headline
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
182
 	    (cl-ppcre:scan org-headline-regexp line)
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
183
 	  (declare (ignore _))
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
184
 	  (when start
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
185
 	    (loop for rs across reg-start
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
186
 		  for re across reg-end
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
187
 		  for i from 0
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
188
 		  do
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
189
 		     (if (= i 0)
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
190
 			 (setf (level self) (- re rs))
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
191
 			 (let ((sub (subseq line rs)))
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
192
 			   (multiple-value-bind (match subs)
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
193
 			       ;; scan for todo-keyword
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
194
 			       (cl-ppcre:scan-to-strings org-todo-keyword-regexp sub)
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
195
 			       (if match
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
196
 				   (let ((k (svref subs 0)))
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
197
 				     (if (org-todo-keyword-p k)
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
198
 					 (setf (state self) (make-org-todo-keyword k)
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
199
 					       (title self) (svref subs 1))
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
200
 					 (setf (title self) match)))
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
201
 				   (setf (title self) sub))))))))
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
202
 	;; scan for tags, modifies title slot
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
203
 	(let ((tag-str (cl-ppcre:scan-to-strings org-tag-regexp (title self))))
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
204
 	  (when tag-str
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
205
 	    (setf (tags self) (apply #'vector (mapcar #'make-org-tag (org-tag-split tag-str)))
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
206
 		  (title self) (subseq (title self) 0 (- (length (title self)) (length tag-str))))))))
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
207
   ;; TODO 2023-07-24: cookies,priority
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
208
   self))
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
209
 
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
210
 (defclass org-todo-keyword (org-element)
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
211
   ((kind :allocation :class :initform :org-todo-keyword)
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
212
    (todo-type :accessor todo-type :initarg :type :initform nil :type symbol)))
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
213
 
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
214
 (defun make-org-todo-keyword (text &optional type) 
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
215
   (make-instance 'org-todo-keyword :text text :type type))
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
216
 
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
217
 (defmethod org-parse ((self org-todo-keyword))
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
218
   (let* ((text (text self))
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
219
 	 (type (gethash (intern text) org-todo-keyword-map nil)))
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
220
     (when type (setf (todo-type self) type))
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
221
     self))
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
222
 
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
223
 (defclass org-list (org-element)
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
224
   ((kind :allocation :class :initform :org-list)))
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
225
 
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
226
 (defclass org-tag (org-element)
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
227
   ((kind :allocation :class :initform :org-tag)))
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
228
 
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
229
 (defun make-org-tag (text) (org-init org-tag text))
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
230
 
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
231
 (defmethod org-parse ((self org-tag)) self) ;; nop
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
232
 
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
233
 (defclass org-block (org-element) ())
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
234
 
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
235
 (defclass org-paragraph (org-element) ())
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
236
 
c30e4700b7c9 cleanup
ellis <ellis@rwest.io>
parents:
diff changeset
237
 (provide :organ)